/** * Given and array of headers and a prefix, job ID, event queue ID, and hash, * add a Message-ID header if needed. * * i.e. if the global includeMessageId is set and there isn't already a * Message-ID in the array. * The message ID is structured the same way as a verp. However no interpretation * is placed on the values received, so they do not need to follow the verp * convention. * * @param array $headers * Array of message headers to update, in-out. * @param string $prefix * Prefix for the message ID, use same prefixes as verp. * wherever possible * @param string $job_id * Job ID component of the generated message ID. * @param string $event_queue_id * Event Queue ID component of the generated message ID. * @param string $hash * Hash component of the generated message ID. * * @return void */ public static function addMessageIdHeader(&$headers, $prefix, $job_id, $event_queue_id, $hash) { $config = CRM_Core_Config::singleton(); $localpart = CRM_Core_BAO_MailSettings::defaultLocalpart(); $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $includeMessageId = CRM_Core_BAO_MailSettings::includeMessageId(); if ($includeMessageId && !array_key_exists('Message-ID', $headers)) { $headers['Message-ID'] = '<' . implode($config->verpSeparator, array($localpart . $prefix, $job_id, $event_queue_id, $hash)) . "@{$emailDomain}>"; } }
/** * Wrapper function to send mail in CiviCRM. Hooks are called from this function. The input parameter * is an associateive array which holds the values of field needed to send an email. These are: * * from : complete from envelope * toName : name of person to send email * toEmail : email address to send to * cc : email addresses to cc * bcc : email addresses to bcc * subject : subject of the email * text : text of the message * html : html version of the message * replyTo : reply-to header in the email * attachments: an associative array of * fullPath : complete pathname to the file * mime_type: mime type of the attachment * cleanName: the user friendly name of the attachmment * * @param array $params (by reference) * * @access public * * @return boolean true if a mail was sent, else false */ static function send(&$params) { $returnPath = CRM_Core_BAO_MailSettings::defaultReturnPath(); $includeMessageId = CRM_Core_BAO_MailSettings::includeMessageId(); $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $from = CRM_Utils_Array::value('from', $params); if (!$returnPath) { $returnPath = self::pluckEmailFromHeader($from); } $params['returnPath'] = $returnPath; // first call the mail alter hook CRM_Utils_Hook::alterMailParams($params); // check if any module has aborted mail sending if (CRM_Utils_Array::value('abortMailSend', $params) || !CRM_Utils_Array::value('toEmail', $params)) { return FALSE; } $textMessage = CRM_Utils_Array::value('text', $params); $htmlMessage = CRM_Utils_Array::value('html', $params); $attachments = CRM_Utils_Array::value('attachments', $params); // CRM-6224 if (trim(CRM_Utils_String::htmlToText($htmlMessage)) == '') { $htmlMessage = FALSE; } $headers = array(); // CRM-10699 support custom email headers if (CRM_Utils_Array::value('headers', $params)) { $headers = array_merge($headers, $params['headers']); } $headers['From'] = $params['from']; $headers['To'] = self::formatRFC822Email(CRM_Utils_Array::value('toName', $params), CRM_Utils_Array::value('toEmail', $params), FALSE); $headers['Cc'] = CRM_Utils_Array::value('cc', $params); $headers['Bcc'] = CRM_Utils_Array::value('bcc', $params); $headers['Subject'] = CRM_Utils_Array::value('subject', $params); $headers['Content-Type'] = $htmlMessage ? 'multipart/mixed; charset=utf-8' : 'text/plain; charset=utf-8'; $headers['Content-Disposition'] = 'inline'; $headers['Content-Transfer-Encoding'] = '8bit'; $headers['Return-Path'] = CRM_Utils_Array::value('returnPath', $params); // CRM-11295: Omit reply-to headers if empty; this avoids issues with overzealous mailservers $replyTo = CRM_Utils_Array::value('replyTo', $params, $from); if (!empty($replyTo)) { $headers['Reply-To'] = $replyTo; } $headers['Date'] = date('r'); if ($includeMessageId) { $headers['Message-ID'] = '<' . uniqid('civicrm_', TRUE) . "@{$emailDomain}>"; } if (CRM_Utils_Array::value('autoSubmitted', $params)) { $headers['Auto-Submitted'] = "Auto-Generated"; } //make sure we has to have space, CRM-6977 foreach (array('From', 'To', 'Cc', 'Bcc', 'Reply-To', 'Return-Path') as $fld) { if (isset($headers[$fld])) { $headers[$fld] = str_replace('"<', '" <', $headers[$fld]); } } // quote FROM, if comma is detected AND is not already quoted. CRM-7053 if (strpos($headers['From'], ',') !== FALSE) { $from = explode(' <', $headers['From']); $headers['From'] = self::formatRFC822Email($from[0], substr(trim($from[1]), 0, -1), TRUE); } require_once 'Mail/mime.php'; $msg = new Mail_mime("\n"); if ($textMessage) { $msg->setTxtBody($textMessage); } if ($htmlMessage) { $msg->setHTMLBody($htmlMessage); } if (!empty($attachments)) { foreach ($attachments as $fileID => $attach) { $msg->addAttachment($attach['fullPath'], $attach['mime_type'], $attach['cleanName']); } } $message = self::setMimeParams($msg); $headers =& $msg->headers($headers); $to = array($params['toEmail']); //get emails from headers, since these are //combination of name and email addresses. if (CRM_Utils_Array::value('Cc', $headers)) { $to[] = CRM_Utils_Array::value('Cc', $headers); } if (CRM_Utils_Array::value('Bcc', $headers)) { $to[] = CRM_Utils_Array::value('Bcc', $headers); unset($headers['Bcc']); } $result = NULL; $mailer = CRM_Core_Config::getMailer(); CRM_Core_Error::ignoreException(); if (is_object($mailer)) { $result = $mailer->send($to, $headers, $message); CRM_Core_Error::setCallback(); if (is_a($result, 'PEAR_Error')) { $message = self::errorMessage($mailer, $result); // append error message in case multiple calls are being made to // this method in the course of sending a batch of messages. CRM_Core_Session::setStatus($message, TRUE); return FALSE; } // CRM-10699 CRM_Utils_Hook::postEmailSend($params); return TRUE; } return FALSE; }