/** * Send an email to a specified user * * @uses $CFG * @param user $user A {@link $USER} object * @param user $from A {@link $USER} object * @param string $subject plain text subject line of the email * @param string $messagetext plain text version of the message * @param string $messagehtml complete html version of the message (optional) * @param string $attachment a file on the filesystem * @param string $attachname the name of the file (extension indicates MIME) * @param bool $usetrueaddress determines whether $from email address should * be sent out. Will be overruled by user profile setting for maildisplay * @return bool|string Returns "true" if mail was sent OK, "emailstop" if email * was blocked by user and "false" if there was another sort of error. */ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '', $attachment = '', $attachname = '', $usetrueaddress = true, $replyto = '', $replytoname = '') { global $CFG; $textlib = textlib_get_instance(); include_once $CFG->libdir . '/phpmailer/class.phpmailer.php'; if (empty($user) || empty($user->email)) { return false; } /* if (over_bounce_threshold($user)) { error_log("User $user->id (".fullname($user).") is over bounce threshold! Not sending."); return false; } */ // this doesn't exist right now, we may bring it in later though. $mail = new phpmailer(); $mail->Version = 'Elgg '; // mailer version (should have $CFG->version on here but we don't have it yet) $mail->PluginDir = $CFG->libdir . '/phpmailer/'; // plugin directory (eg smtp plugin) $mail->CharSet = 'UTF-8'; // everything is now uft8 if (empty($CFG->smtphosts)) { $mail->IsMail(); // use PHP mail() = sendmail } else { if ($CFG->smtphosts == 'qmail') { $mail->IsQmail(); // use Qmail system } else { $mail->IsSMTP(); // use SMTP directly if ($CFG->debug > 7) { echo '<pre>' . "\n"; $mail->SMTPDebug = true; } $mail->Host = $CFG->smtphosts; // specify main and backup servers if ($CFG->smtpuser) { // Use SMTP authentication $mail->SMTPAuth = true; $mail->Username = $CFG->smtpuser; $mail->Password = $CFG->smtppass; } } } /* not here yet, leave it in just in case. // make up an email address for handling bounces if (!empty($CFG->handlebounces)) { $modargs = 'B'.base64_encode(pack('V',$user->ident)).substr(md5($user->email),0,16); $mail->Sender = generate_email_processing_address(0,$modargs); } else { $mail->Sender = $CFG->sysadminemail; } */ $mail->Sender = $CFG->sysadminemail; // for elgg. delete if we change the above. // TODO add a preference for maildisplay if (is_string($from)) { // So we can pass whatever we want if there is need $mail->From = $CFG->noreplyaddress; $mail->FromName = $from; } else { if (empty($from)) { // make stuff up $mail->From = $CFG->sysadminemail; $mail->FromName = $CFG->sitename . ' ' . __gettext('Administrator'); } else { if ($usetrueaddress and !empty($from->maildisplay)) { $mail->From = $from->email; $mail->FromName = $from->name; } else { $mail->From = $CFG->noreplyaddress; $mail->FromName = $from->name; if (empty($replyto)) { $mail->AddReplyTo($CFG->noreplyaddress, __gettext('Do not reply')); } } } } if (!empty($replyto)) { $mail->AddReplyTo($replyto, $replytoname); } $mail->Subject = $textlib->substr(stripslashes($subject), 0, 900); $mail->AddAddress($user->email, $user->name); $mail->WordWrap = 79; // set word wrap if (!empty($from->customheaders)) { // Add custom headers if (is_array($from->customheaders)) { foreach ($from->customheaders as $customheader) { $mail->AddCustomHeader($customheader); } } else { $mail->AddCustomHeader($from->customheaders); } } if (!empty($from->priority)) { $mail->Priority = $from->priority; } //TODO add a user preference for this. right now just send plaintext $user->mailformat = 0; if ($messagehtml && $user->mailformat == 1) { // Don't ever send HTML to users who don't want it $mail->IsHTML(true); $mail->Encoding = 'quoted-printable'; // Encoding to use $mail->Body = $messagehtml; $mail->AltBody = "\n{$messagetext}\n"; } else { $mail->IsHTML(false); $mail->Body = "\n{$messagetext}\n"; } if ($attachment && $attachname) { if (ereg("\\.\\.", $attachment)) { // Security check for ".." in dir path $mail->AddAddress($CFG->sysadminemail, $CFG->sitename . ' ' . __gettext('Administrator')); $mail->AddStringAttachment('Error in attachment. User attempted to attach a filename with a unsafe name.', 'error.txt', '8bit', 'text/plain'); } else { require_once $CFG->libdir . '/filelib.php'; $mimetype = mimeinfo('type', $attachname); $mail->AddAttachment($attachment, $attachname, 'base64', $mimetype); } } if ($mail->Send()) { // set_send_count($user); // later return true; } else { mtrace('ERROR: ' . $mail->ErrorInfo); return false; } }
/** * Send an email to a specified user * * @uses $CFG * @uses $FULLME * @uses SITEID * @param user $user A {@link $USER} object * @param user $from A {@link $USER} object * @param string $subject plain text subject line of the email * @param string $messagetext plain text version of the message * @param string $messagehtml complete html version of the message (optional) * @param string $attachment a file on the filesystem, relative to $CFG->dataroot * @param string $attachname the name of the file (extension indicates MIME) * @param bool $usetrueaddress determines whether $from email address should * be sent out. Will be overruled by user profile setting for maildisplay * @return bool|string Returns "true" if mail was sent OK, "emailstop" if email * was blocked by user and "false" if there was another sort of error. */ function email_to_user($user, $from, $subject, $messagetext, $messagehtml = '', $attachment = '', $attachname = '', $usetrueaddress = true, $replyto = '', $replytoname = '') { global $CFG, $FULLME; include_once $CFG->libdir . '/phpmailer/class.phpmailer.php'; /// We are going to use textlib services here $textlib = textlib_get_instance(); if (empty($user)) { return false; } // skip mail to suspended users if (isset($user->auth) && $user->auth == 'nologin') { return true; } if (!empty($user->emailstop)) { return 'emailstop'; } if (over_bounce_threshold($user)) { error_log("User {$user->id} (" . fullname($user) . ") is over bounce threshold! Not sending."); return false; } $mail = new phpmailer(); $mail->Version = 'Moodle ' . $CFG->version; // mailer version $mail->PluginDir = $CFG->libdir . '/phpmailer/'; // plugin directory (eg smtp plugin) $mail->CharSet = 'UTF-8'; if ($CFG->smtphosts == 'qmail') { $mail->IsQmail(); // use Qmail system } else { if (empty($CFG->smtphosts)) { $mail->IsMail(); // use PHP mail() = sendmail } else { $mail->IsSMTP(); // use SMTP directly if (!empty($CFG->debugsmtp)) { echo '<pre>' . "\n"; $mail->SMTPDebug = true; } $mail->Host = $CFG->smtphosts; // specify main and backup servers if ($CFG->smtpuser) { // Use SMTP authentication $mail->SMTPAuth = true; $mail->Username = $CFG->smtpuser; $mail->Password = $CFG->smtppass; } } } $supportuser = generate_email_supportuser(); // make up an email address for handling bounces if (!empty($CFG->handlebounces)) { $modargs = 'B' . base64_encode(pack('V', $user->id)) . substr(md5($user->email), 0, 16); $mail->Sender = generate_email_processing_address(0, $modargs); } else { $mail->Sender = $supportuser->email; } if (is_string($from)) { // So we can pass whatever we want if there is need $mail->From = $CFG->noreplyaddress; $mail->FromName = $from; } else { if ($usetrueaddress and $from->maildisplay) { $mail->From = $from->email; $mail->FromName = fullname($from); } else { $mail->From = $CFG->noreplyaddress; $mail->FromName = fullname($from); if (empty($replyto)) { $mail->AddReplyTo($CFG->noreplyaddress, get_string('noreplyname')); } } } if (!empty($replyto)) { $mail->AddReplyTo($replyto, $replytoname); } $mail->Subject = substr(stripslashes($subject), 0, 900); $mail->AddAddress($user->email, fullname($user)); $mail->WordWrap = 79; // set word wrap if (!empty($from->customheaders)) { // Add custom headers if (is_array($from->customheaders)) { foreach ($from->customheaders as $customheader) { $mail->AddCustomHeader($customheader); } } else { $mail->AddCustomHeader($from->customheaders); } } if (!empty($from->priority)) { $mail->Priority = $from->priority; } if ($messagehtml && $user->mailformat == 1) { // Don't ever send HTML to users who don't want it $mail->IsHTML(true); $mail->Encoding = 'quoted-printable'; // Encoding to use $mail->Body = $messagehtml; $mail->AltBody = "\n{$messagetext}\n"; } else { $mail->IsHTML(false); $mail->Body = "\n{$messagetext}\n"; } if ($attachment && $attachname) { if (ereg("\\.\\.", $attachment)) { // Security check for ".." in dir path $mail->AddAddress($supportuser->email, fullname($supportuser, true)); $mail->AddStringAttachment('Error in attachment. User attempted to attach a filename with a unsafe name.', 'error.txt', '8bit', 'text/plain'); } else { require_once $CFG->libdir . '/filelib.php'; $mimetype = mimeinfo('type', $attachname); $mail->AddAttachment($CFG->dataroot . '/' . $attachment, $attachname, 'base64', $mimetype); } } /// If we are running under Unicode and sitemailcharset or allowusermailcharset are set, convert the email /// encoding to the specified one if (!empty($CFG->sitemailcharset) || !empty($CFG->allowusermailcharset)) { /// Set it to site mail charset $charset = $CFG->sitemailcharset; /// Overwrite it with the user mail charset if (!empty($CFG->allowusermailcharset)) { if ($useremailcharset = get_user_preferences('mailcharset', '0', $user->id)) { $charset = $useremailcharset; } } /// If it has changed, convert all the necessary strings $charsets = get_list_of_charsets(); unset($charsets['UTF-8']); if (in_array($charset, $charsets)) { /// Save the new mail charset $mail->CharSet = $charset; /// And convert some strings $mail->FromName = $textlib->convert($mail->FromName, 'utf-8', $mail->CharSet); //From Name foreach ($mail->ReplyTo as $key => $rt) { //ReplyTo Names $mail->ReplyTo[$key][1] = $textlib->convert($rt, 'utf-8', $mail->CharSet); } $mail->Subject = $textlib->convert($mail->Subject, 'utf-8', $mail->CharSet); //Subject foreach ($mail->to as $key => $to) { $mail->to[$key][1] = $textlib->convert($to, 'utf-8', $mail->CharSet); //To Names } $mail->Body = $textlib->convert($mail->Body, 'utf-8', $mail->CharSet); //Body $mail->AltBody = $textlib->convert($mail->AltBody, 'utf-8', $mail->CharSet); //Subject } } if ($mail->Send()) { set_send_count($user); $mail->IsSMTP(); // use SMTP directly if (!empty($CFG->debugsmtp)) { echo '</pre>'; } return true; } else { mtrace('ERROR: ' . $mail->ErrorInfo); add_to_log(SITEID, 'library', 'mailer', $FULLME, 'ERROR: ' . $mail->ErrorInfo); if (!empty($CFG->debugsmtp)) { echo '</pre>'; } return false; } }
function emailSend($data) { $stime = array_sum(explode(' ', microtime())); require_once "getmxrr.php"; $smtp =& $this->params; $mail = new phpmailer(); $mail->Mailer = "smtp"; $mail->From = isset($data['from']) & !empty($data['from']) ? $data['from'] : '*****@*****.**'; $mail->FromName = isset($data['fromName']) & !empty($data['fromName']) ? $data['fromName'] : 'RuSoft'; $mail->Sender = isset($data['from']) & !empty($data['from']) ? $data['from'] : '*****@*****.**'; $mail->Host = $smtp['host']; $mail->CharSet = $smtp['charset']; $mail->Encoding = $smtp['encoding']; $mail->Port = $smtp['port']; $mail->SMTPAuth = $smtp['auth']; $mail->Subject = isset($data['subj']) & !empty($data['subj']) ? $data['subj'] : ''; if ($smtp['auth']) { $mail->Username = $smtp['user']; $mail->Password = $smtp['pass']; } // HTML body if (isset($data['mess']['html']) & !empty($data['mess']['html'])) { $body = $data['mess']['html']; $mail->isHTML(true); } // Plain text body (for mail clients that cannot read HTML) if (isset($data['mess']['text']) & !empty($data['mess']['text'])) { $text_body = $data['mess']['text']; $mail->isHTML(false); } $mail->AltBody = isset($text_body) ? $text_body : ''; $mail->Body = isset($body) ? $body : (isset($text_body) ? $text_body : ''); $i = 1; // порядковый номер файла //добавляем файлы прикрепленные файлы if (isset($data['attachment']) & !empty($data['attachment'])) { foreach ($data['attachment'] as $k => $item) { if (isset($item['binary']) & !empty($item['binary'])) { $mail->AddStringAttachment($item["binary"], isset($item["name"]) & !empty($item["name"]) ? $item["name"] : 'file' . $i, $smtp['encoding']); $i++; } elseif (isset($item['path']) & !empty($item['path'])) { $mail->AddAttachment($item["path"], isset($item["name"]) & !empty($item["name"]) ? $item["name"] : 'file' . $i, $smtp['encoding']); $i++; } } } // добавляем файлы, отображаемые на странице if (isset($data['embedded']) & !empty($data['embedded'])) { foreach ($data['embedded'] as $k => $item) { if (isset($item['path']) & !empty($item['path'])) { $mail->AddEmbeddedImage($item["path"], isset($item["cid"]) & !empty($item["cid"]) ? $item["cid"] : $i, isset($item["name"]) & !empty($item["name"]) ? $item["name"] : 'file' . $i, $smtp['encoding']); $i++; } } } //pr($mail); //на данном этапе имеется уже собранное письмо и нам необходимо определить mx серверы для отправки...для каждого письма. //чтобы повторно не искать серверы в момент отправки для каждого... //сохраняем для каждого домена один и тот же сервер $mxsrvs = array(); $mxemails = array(); $debug['ctime'] = round((array_sum(explode(' ', microtime())) - $stime) * 1000, 2) . " ms"; foreach ($data['to'] as $email => $name) { //берем чисто host if (!$this->_is_valid_email($email)) { $debug['emails'][$email]['error'] = "неправильно указан email адрес."; continue; } $host = substr($email, strpos($email, "@") + 1); $domains = explode(".", $host); foreach ($domains as $level => $domain) { $address = implode(".", $domains); if (!key_exists($address, $mxsrvs)) { $time = array_sum(explode(' ', microtime())); if (getmxrr_portable($address, $mxhosts, $preference) == true) { array_multisort($preference, $mxhosts); } $debug['emails'][$email]['mxtime'] = round((array_sum(explode(' ', microtime())) - $time) * 1000, 2) . " ms"; if (!empty($mxhosts)) { $mxhosts[] = $smtp['host']; //потому что shadow тормознутый сервак if (in_array('shadow.rusoft.ru', $mxhosts)) { unset($mxhosts[0]); } //чтобы включить рассылку на smtp серверы получателей, необходимо закоментировать следующую строчку $mxhosts = array_reverse($mxhosts); $mxsrvs[$address] = $mxhosts; $mxemails[$email] =& $mxsrvs[$address]; $debug['emails'][$email]['mxsrvs'] =& $mxsrvs[$address]; break; } else { unset($domains[$level]); } } else { $debug['emails'][$email]['mxtime'] = 'cache(0 ms)'; $mxemails[$email] =& $mxsrvs[$address]; $debug['emails'][$email]['mxsrvs'] =& $mxsrvs[$address]; } } } //получены все mx северы и теперь начинаем отправку по списку foreach ($mxemails as $email => $mxs) { //проверяем email адрес на существование и работу mx сервера //можно включить проверку, но это 1) замедляет, 2) вероятность очень низкая //$this->checkEmail($email, $mxs, $debug); $mail->AddAddress($email, $name); foreach ($mxs as $k => $host) { $mail->Host = $host; $time = array_sum(explode(' ', microtime())); $status = $mail->Send(); $debug['emails'][$email]['sendtime'] = round((array_sum(explode(' ', microtime())) - $time) * 1000, 2) . " ms"; $debug['emails'][$email]['status'] = $status; if ($status) { $debug['emails'][$email]['host'] = $host; break; } } $mail->ClearAddresses(); } $debug['time'] = round((array_sum(explode(' ', microtime())) - $stime) * 1000, 2) . " ms"; if (function_exists('log_notice')) { //скидываем в лог информацию о отправленных сообщениях $str = "<b>Были отправлены следующие сообщения:</b><br>Время генерации шалона для отправки: " . $debug['ctime'] . "<br>Общее время: " . $debug['time'] . "<br><b>Адреса:</b><br>"; foreach ($debug['emails'] as $k => $v) { $str .= "<br> <b><font color='blue'>" . $k . "</font></b>"; $str .= "<br> Определение smtp серверов: " . $v['mxtime']; $str .= "<br> Отправлено через: " . $v['host']; $str .= "<br> Время отправления: " . $v['sendtime']; $str .= "<br> Статус: " . ($v['status'] ? '<font color="green">успешно</font>' : '<font color="red">неудачно</font>'); } log_notice('email', false, $str); } //$status = true; // Clear attachments for next loop $mail->ClearAttachments(); if ($status) { return true; } return false; }