function testHtmlToText() { foreach ($this->_testInput as $html => $text) { $output = CRM_Utils_String::htmlToText($html); $this->assertEquals(trim($output), trim($text), "Text Output did not match for {$html}"); } }
/** * Perform an upgrade without using the web-frontend * * @param bool $enablePrint * * @throws Exception * @return array, with keys: * - message: string, HTML-ish blob */ public function run($enablePrint = TRUE) { // lets get around the time limit issue if possible for upgrades if (!ini_get('safe_mode')) { set_time_limit(0); } $upgrade = new CRM_Upgrade_Form(); list($currentVer, $latestVer) = $upgrade->getUpgradeVersions(); if ($error = $upgrade->checkUpgradeableVersion($currentVer, $latestVer)) { throw new Exception($error); } // Disable our SQL triggers CRM_Core_DAO::dropTriggers(); // CRM-11156 $preUpgradeMessage = NULL; $upgrade->setPreUpgradeMessage($preUpgradeMessage, $currentVer, $latestVer); $postUpgradeMessageFile = CRM_Utils_File::tempnam('civicrm-post-upgrade'); $queueRunner = new CRM_Queue_Runner(array('title' => ts('CiviCRM Upgrade Tasks'), 'queue' => CRM_Upgrade_Form::buildQueue($currentVer, $latestVer, $postUpgradeMessageFile))); $queueResult = $queueRunner->runAll(); if ($queueResult !== TRUE) { $errorMessage = CRM_Core_Error::formatTextException($queueResult['exception']); CRM_Core_Error::debug_log_message($errorMessage); if ($enablePrint) { print $errorMessage; } throw $queueResult['exception']; // FIXME test } CRM_Upgrade_Form::doFinish(); $message = file_get_contents($postUpgradeMessageFile); return array('latestVer' => $latestVer, 'message' => $message, 'text' => CRM_Utils_String::htmlToText($message)); }
/** * 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; }
/** * Confirm a pending subscription * * @param int $contact_id The id of the contact * @param int $subscribe_id The id of the subscription event * @param string $hash The hash * @return boolean True on success * @access public * @static */ public static function confirm($contact_id, $subscribe_id, $hash) { require_once 'CRM/Mailing/Event/BAO/Subscribe.php'; $se =& CRM_Mailing_Event_BAO_Subscribe::verify($contact_id, $subscribe_id, $hash); if (!$se) { return false; } require_once 'CRM/Core/Transaction.php'; $transaction = new CRM_Core_Transaction(); $ce =& new CRM_Mailing_Event_BAO_Confirm(); $ce->event_subscribe_id = $se->id; $ce->time_stamp = date('YmdHis'); $ce->save(); require_once 'CRM/Contact/BAO/GroupContact.php'; CRM_Contact_BAO_GroupContact::updateGroupMembershipStatus($contact_id, $se->group_id, 'Email', $ce->id); $transaction->commit(); $config =& CRM_Core_Config::singleton(); require_once 'CRM/Core/BAO/Domain.php'; $domain =& CRM_Core_BAO_Domain::getDomain(); list($domainEmailName, $_) = CRM_Core_BAO_Domain::getNameAndEmail(); require_once 'CRM/Contact/BAO/Contact/Location.php'; list($display_name, $email) = CRM_Contact_BAO_Contact_Location::getEmailDetails($se->contact_id); require_once 'CRM/Contact/DAO/Group.php'; $group =& new CRM_Contact_DAO_Group(); $group->id = $se->group_id; $group->find(true); require_once 'CRM/Mailing/BAO/Component.php'; $component =& new CRM_Mailing_BAO_Component(); $component->is_default = 1; $component->is_active = 1; $component->component_type = 'Welcome'; $component->find(true); require_once 'CRM/Core/BAO/MailSettings.php'; $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $headers = array('Subject' => $component->subject, 'From' => "\"{$domainEmailName}\" <do-not-reply@{$emailDomain}>", 'To' => $email, 'Reply-To' => "do-not-reply@{$emailDomain}", 'Return-Path' => "do-not-reply@{$emailDomain}"); $html = $component->body_html; if ($component->body_text) { $text = $component->body_text; } else { $text = CRM_Utils_String::htmlToText($component->body_html); } require_once 'CRM/Mailing/BAO/Mailing.php'; $bao =& new CRM_Mailing_BAO_Mailing(); $bao->body_text = $text; $bao->body_html = $html; $tokens = $bao->getTokens(); require_once 'CRM/Utils/Token.php'; $html = CRM_Utils_Token::replaceDomainTokens($html, $domain, true, $tokens['html']); $html = CRM_Utils_Token::replaceWelcomeTokens($html, $group->title, true); $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, false, $tokens['text']); $text = CRM_Utils_Token::replaceWelcomeTokens($text, $group->title, false); // we need to wrap Mail_mime because PEAR is apparently unable to fix // a six-year-old bug (PEAR bug #30) in Mail_mime::_encodeHeaders() // this fixes CRM-5466 require_once 'CRM/Utils/Mail/FixedMailMIME.php'; $message =& new CRM_Utils_Mail_FixedMailMIME("\n"); $message->setHTMLBody($html); $message->setTxtBody($text); $b =& CRM_Utils_Mail::setMimeParams($message); $h =& $message->headers($headers); $mailer =& $config->getMailer(); require_once 'CRM/Mailing/BAO/Mailing.php'; PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array('CRM_Core_Error', 'nullHandler')); if (is_object($mailer)) { $mailer->send($email, $h, $b); CRM_Core_Error::setCallback(); } return $group->title; }
/** * Send a response email informing the contact of the groups from which he. * has been unsubscribed. * * @param string $queue_id * The queue event ID. * @param array $groups * List of group IDs. * @param bool $is_domain * Is this domain-level?. * @param int $job * The job ID. */ public static function send_unsub_response($queue_id, $groups, $is_domain = FALSE, $job) { $config = CRM_Core_Config::singleton(); $domain = CRM_Core_BAO_Domain::getDomain(); $jobObject = new CRM_Mailing_BAO_MailingJob(); $jobTable = $jobObject->getTableName(); $mailingObject = new CRM_Mailing_DAO_Mailing(); $mailingTable = $mailingObject->getTableName(); $contactsObject = new CRM_Contact_DAO_Contact(); $contacts = $contactsObject->getTableName(); $emailObject = new CRM_Core_DAO_Email(); $email = $emailObject->getTableName(); $queueObject = new CRM_Mailing_Event_BAO_Queue(); $queue = $queueObject->getTableName(); //get the default domain email address. list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail(); $dao = new CRM_Mailing_BAO_Mailing(); $dao->query(" SELECT * FROM {$mailingTable}\n INNER JOIN {$jobTable} ON\n {$jobTable}.mailing_id = {$mailingTable}.id\n WHERE {$jobTable}.id = {$job}"); $dao->fetch(); $component = new CRM_Mailing_BAO_Component(); if ($is_domain) { $component->id = $dao->optout_id; } else { $component->id = $dao->unsubscribe_id; } $component->find(TRUE); $html = $component->body_html; if ($component->body_text) { $text = $component->body_text; } else { $text = CRM_Utils_String::htmlToText($component->body_html); } $eq = new CRM_Core_DAO(); $eq->query("SELECT {$contacts}.preferred_mail_format as format,\n {$contacts}.id as contact_id,\n {$email}.email as email,\n {$queue}.hash as hash\n FROM {$contacts}\n INNER JOIN {$queue} ON {$queue}.contact_id = {$contacts}.id\n INNER JOIN {$email} ON {$queue}.email_id = {$email}.id\n WHERE {$queue}.id = " . CRM_Utils_Type::escape($queue_id, 'Integer')); $eq->fetch(); if ($groups) { foreach ($groups as $key => $value) { if (!$value) { unset($groups[$key]); } } } $message = new Mail_mime("\n"); list($addresses, $urls) = CRM_Mailing_BAO_Mailing::getVerpAndUrls($job, $queue_id, $eq->hash, $eq->email); $bao = new CRM_Mailing_BAO_Mailing(); $bao->body_text = $text; $bao->body_html = $html; $tokens = $bao->getTokens(); if ($eq->format == 'HTML' || $eq->format == 'Both') { $html = CRM_Utils_Token::replaceDomainTokens($html, $domain, TRUE, $tokens['html']); $html = CRM_Utils_Token::replaceUnsubscribeTokens($html, $domain, $groups, TRUE, $eq->contact_id, $eq->hash); $html = CRM_Utils_Token::replaceActionTokens($html, $addresses, $urls, TRUE, $tokens['html']); $html = CRM_Utils_Token::replaceMailingTokens($html, $dao, NULL, $tokens['html']); $message->setHTMLBody($html); } if (!$html || $eq->format == 'Text' || $eq->format == 'Both') { $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, FALSE, $tokens['text']); $text = CRM_Utils_Token::replaceUnsubscribeTokens($text, $domain, $groups, FALSE, $eq->contact_id, $eq->hash); $text = CRM_Utils_Token::replaceActionTokens($text, $addresses, $urls, FALSE, $tokens['text']); $text = CRM_Utils_Token::replaceMailingTokens($text, $dao, NULL, $tokens['text']); $message->setTxtBody($text); } $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $headers = array('Subject' => $component->subject, 'From' => "\"{$domainEmailName}\" <do-not-reply@{$emailDomain}>", 'To' => $eq->email, 'Reply-To' => "do-not-reply@{$emailDomain}", 'Return-Path' => "do-not-reply@{$emailDomain}"); CRM_Mailing_BAO_Mailing::addMessageIdHeader($headers, 'u', $job, $queue_id, $eq->hash); $b = CRM_Utils_Mail::setMimeParams($message); $h = $message->headers($headers); $mailer = \Civi::service('pear_mail'); if (is_object($mailer)) { $errorScope = CRM_Core_TemporaryErrorScope::ignoreException(); $mailer->send($eq->email, $h, $b); unset($errorScope); } }
static function sendReminder($contactId, $email, $scheduleID, $from, $tokenParams) { $schedule = new CRM_Core_DAO_ActionSchedule(); $schedule->id = $scheduleID; $domain = CRM_Core_BAO_Domain::getDomain(); $result = NULL; $hookTokens = array(); if ($schedule->find(TRUE)) { $body_text = $schedule->body_text; $body_html = $schedule->body_html; $body_subject = $schedule->subject; if (!$body_text) { $body_text = CRM_Utils_String::htmlToText($body_html); } $params = array(array('contact_id', '=', $contactId, 0, 0)); list($contact, $_) = CRM_Contact_BAO_Query::apiQuery($params); //CRM-4524 $contact = reset($contact); if (!$contact || is_a($contact, 'CRM_Core_Error')) { return NULL; } // merge activity tokens with contact array $contact = array_merge($contact, $tokenParams); //CRM-5734 CRM_Utils_Hook::tokenValues($contact, $contactId); CRM_Utils_Hook::tokens($hookTokens); $categories = array_keys($hookTokens); $type = array('html', 'text'); foreach ($type as $key => $value) { $dummy_mail = new CRM_Mailing_BAO_Mailing(); $bodyType = "body_{$value}"; $dummy_mail->{$bodyType} = ${$bodyType}; $tokens = $dummy_mail->getTokens(); if (${$bodyType}) { CRM_Utils_Token::replaceGreetingTokens(${$bodyType}, NULL, $contact['contact_id']); ${$bodyType} = CRM_Utils_Token::replaceDomainTokens(${$bodyType}, $domain, TRUE, $tokens[$value], TRUE); ${$bodyType} = CRM_Utils_Token::replaceContactTokens(${$bodyType}, $contact, FALSE, $tokens[$value], FALSE, TRUE); ${$bodyType} = CRM_Utils_Token::replaceComponentTokens(${$bodyType}, $contact, $tokens[$value], TRUE, FALSE); ${$bodyType} = CRM_Utils_Token::replaceHookTokens(${$bodyType}, $contact, $categories, TRUE); } } $html = $body_html; $text = $body_text; $smarty = CRM_Core_Smarty::singleton(); foreach (array('text', 'html') as $elem) { ${$elem} = $smarty->fetch("string:{${$elem}}"); } $matches = array(); preg_match_all('/(?<!\\{|\\\\)\\{(\\w+\\.\\w+)\\}(?!\\})/', $body_subject, $matches, PREG_PATTERN_ORDER); $subjectToken = NULL; if ($matches[1]) { foreach ($matches[1] as $token) { list($type, $name) = preg_split('/\\./', $token, 2); if ($name) { if (!isset($subjectToken['contact'])) { $subjectToken['contact'] = array(); } $subjectToken['contact'][] = $name; } } } $messageSubject = CRM_Utils_Token::replaceContactTokens($body_subject, $contact, FALSE, $subjectToken); $messageSubject = CRM_Utils_Token::replaceDomainTokens($messageSubject, $domain, TRUE, $tokens[$value]); $messageSubject = CRM_Utils_Token::replaceComponentTokens($messageSubject, $contact, $tokens[$value], TRUE); $messageSubject = CRM_Utils_Token::replaceHookTokens($messageSubject, $contact, $categories, TRUE); $messageSubject = $smarty->fetch("string:{$messageSubject}"); // set up the parameters for CRM_Utils_Mail::send $mailParams = array('groupName' => 'Scheduled Reminder Sender', 'from' => $from, 'toName' => $contact['display_name'], 'toEmail' => $email, 'subject' => $messageSubject); if (!$html || $contact['preferred_mail_format'] == 'Text' || $contact['preferred_mail_format'] == 'Both') { // render the & entities in text mode, so that the links work $mailParams['text'] = str_replace('&', '&', $text); } if ($html && ($contact['preferred_mail_format'] == 'HTML' || $contact['preferred_mail_format'] == 'Both')) { $mailParams['html'] = $html; } $result = CRM_Utils_Mail::send($mailParams); } $schedule->free(); return $result; }
/** * Confirm a pending subscription * * @param int $contact_id The id of the contact * @param int $subscribe_id The id of the subscription event * @param string $hash The hash * * @return boolean True on success * @access public * @static */ public static function confirm($contact_id, $subscribe_id, $hash) { $se =& CRM_Mailing_Event_BAO_Subscribe::verify($contact_id, $subscribe_id, $hash); if (!$se) { return FALSE; } // before we proceed lets just check if this contact is already 'Added' // if so, we should ignore this request and hence avoid sending multiple // emails - CRM-11157 $details = CRM_Contact_BAO_GroupContact::getMembershipDetail($contact_id, $se->group_id); if ($details && $details->status == 'Added') { // This contact is already subscribed // lets return the group title return CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Group', $se->group_id, 'title'); } $transaction = new CRM_Core_Transaction(); $ce = new CRM_Mailing_Event_BAO_Confirm(); $ce->event_subscribe_id = $se->id; $ce->time_stamp = date('YmdHis'); $ce->save(); CRM_Contact_BAO_GroupContact::addContactsToGroup(array($contact_id), $se->group_id, 'Email', 'Added', $ce->id); $transaction->commit(); $config = CRM_Core_Config::singleton(); $domain = CRM_Core_BAO_Domain::getDomain(); list($domainEmailName, $_) = CRM_Core_BAO_Domain::getNameAndEmail(); list($display_name, $email) = CRM_Contact_BAO_Contact_Location::getEmailDetails($se->contact_id); $group = new CRM_Contact_DAO_Group(); $group->id = $se->group_id; $group->find(TRUE); $component = new CRM_Mailing_BAO_Component(); $component->is_default = 1; $component->is_active = 1; $component->component_type = 'Welcome'; $component->find(TRUE); $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $html = $component->body_html; if ($component->body_text) { $text = $component->body_text; } else { $text = CRM_Utils_String::htmlToText($component->body_html); } $bao = new CRM_Mailing_BAO_Mailing(); $bao->body_text = $text; $bao->body_html = $html; $tokens = $bao->getTokens(); $html = CRM_Utils_Token::replaceDomainTokens($html, $domain, TRUE, $tokens['html']); $html = CRM_Utils_Token::replaceWelcomeTokens($html, $group->title, TRUE); $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, FALSE, $tokens['text']); $text = CRM_Utils_Token::replaceWelcomeTokens($text, $group->title, FALSE); $mailParams = array('groupName' => 'Mailing Event ' . $component->component_type, 'subject' => $component->subject, 'from' => "\"{$domainEmailName}\" <do-not-reply@{$emailDomain}>", 'toEmail' => $email, 'toName' => $display_name, 'replyTo' => "do-not-reply@{$emailDomain}", 'returnPath' => "do-not-reply@{$emailDomain}", 'html' => $html, 'text' => $text); // send - ignore errors because the desired status change has already been successful $unused_result = CRM_Utils_Mail::send($mailParams); return $group->title; }
/** * @param string $html * Example HTML input. * @param string $text * Expected text output. * @dataProvider htmlToTextExamples */ public function testHtmlToText($html, $text) { $output = CRM_Utils_String::htmlToText($html); $this->assertEquals(trim($output), trim($text), "Text Output did not match for {$html}"); }
/** * Retrieve a ref to an array that holds the email and text templates for this email * assembles the complete template including the header and footer * that the user has uploaded or declared (if they have dome that) * * @return array * reference to an assoc array */ private function &getTemplates() { if (!$this->templates) { $this->getHeaderFooter(); $this->templates = array(); if ($this->body_text) { $template = array(); if ($this->header) { $template[] = $this->header->body_text; } $template[] = $this->body_text; if ($this->footer) { $template[] = $this->footer->body_text; } $this->templates['text'] = implode("\n", $template); } if ($this->body_html) { $template = array(); if ($this->header) { $template[] = $this->header->body_html; } $template[] = $this->body_html; if ($this->footer) { $template[] = $this->footer->body_html; } $this->templates['html'] = implode("\n", $template); // this is where we create a text template from the html template if the text template did not exist // this way we ensure that every recipient will receive an email even if the pref is set to text and the // user uploads an html email only if (!$this->body_text) { $this->templates['text'] = CRM_Utils_String::htmlToText($this->templates['html']); } } if ($this->subject) { $template = array(); $template[] = $this->subject; $this->templates['subject'] = implode("\n", $template); } } return $this->templates; }
/** * @param \Civi\Token\TokenRow $tokenRow * @param CRM_Core_DAO_ActionSchedule $schedule * @param int $toContactID * @return array * List of error messages. */ protected static function sendReminderEmail($tokenRow, $schedule, $toContactID) { $toEmail = CRM_Contact_BAO_Contact::getPrimaryEmail($toContactID); if (!$toEmail) { return array("email_missing" => "Couldn't find recipient's email address."); } $body_text = $tokenRow->render('body_text'); $body_html = $tokenRow->render('body_html'); if (!$schedule->body_text) { $body_text = CRM_Utils_String::htmlToText($body_html); } // set up the parameters for CRM_Utils_Mail::send $mailParams = array('groupName' => 'Scheduled Reminder Sender', 'from' => self::pickFromEmail($schedule), 'toName' => $tokenRow->context['contact']['display_name'], 'toEmail' => $toEmail, 'subject' => $tokenRow->render('subject'), 'entity' => 'action_schedule', 'entity_id' => $schedule->id); if (!$body_html || $tokenRow->context['contact']['preferred_mail_format'] == 'Text' || $tokenRow->context['contact']['preferred_mail_format'] == 'Both') { // render the & entities in text mode, so that the links work $mailParams['text'] = str_replace('&', '&', $body_text); } if ($body_html && ($tokenRow->context['contact']['preferred_mail_format'] == 'HTML' || $tokenRow->context['contact']['preferred_mail_format'] == 'Both')) { $mailParams['html'] = $body_html; } $result = CRM_Utils_Mail::send($mailParams); if (!$result || is_a($result, 'PEAR_Error')) { return array('email_fail' => 'Failed to send message'); } return array(); }
/** * Send an automated response. * * @param object $mailing * The mailing object. * @param int $queue_id * The queue ID. * @param string $replyto * Optional reply-to from the reply. * * @return void */ private static function autoRespond(&$mailing, $queue_id, $replyto) { $config = CRM_Core_Config::singleton(); $contacts = CRM_Contact_DAO_Contact::getTableName(); $email = CRM_Core_DAO_Email::getTableName(); $queue = CRM_Mailing_Event_DAO_Queue::getTableName(); $eq = new CRM_Core_DAO(); $eq->query("SELECT {$contacts}.preferred_mail_format as format,\n {$email}.email as email,\n {$queue}.job_id as job_id,\n {$queue}.hash as hash\n FROM {$contacts}\n INNER JOIN {$queue} ON {$queue}.contact_id = {$contacts}.id\n INNER JOIN {$email} ON {$queue}.email_id = {$email}.id\n WHERE {$queue}.id = " . CRM_Utils_Type::escape($queue_id, 'Integer')); $eq->fetch(); $to = empty($replyto) ? $eq->email : $replyto; $component = new CRM_Mailing_BAO_Component(); $component->id = $mailing->reply_id; $component->find(TRUE); $message = new Mail_Mime("\n"); $domain = CRM_Core_BAO_Domain::getDomain(); list($domainEmailName, $_) = CRM_Core_BAO_Domain::getNameAndEmail(); $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $headers = array('Subject' => $component->subject, 'To' => $to, 'From' => "\"{$domainEmailName}\" <do-not-reply@{$emailDomain}>", 'Reply-To' => "do-not-reply@{$emailDomain}", 'Return-Path' => "do-not-reply@{$emailDomain}"); /* TODO: do we need reply tokens? */ $html = $component->body_html; if ($component->body_text) { $text = $component->body_text; } else { $text = CRM_Utils_String::htmlToText($component->body_html); } $bao = new CRM_Mailing_BAO_Mailing(); $bao->body_text = $text; $bao->body_html = $html; $tokens = $bao->getTokens(); if ($eq->format == 'HTML' || $eq->format == 'Both') { $html = CRM_Utils_Token::replaceDomainTokens($html, $domain, TRUE, $tokens['html']); $html = CRM_Utils_Token::replaceMailingTokens($html, $mailing, NULL, $tokens['html']); $message->setHTMLBody($html); } if (!$html || $eq->format == 'Text' || $eq->format == 'Both') { $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, FALSE, $tokens['text']); $text = CRM_Utils_Token::replaceMailingTokens($text, $mailing, NULL, $tokens['text']); $message->setTxtBody($text); } $b = CRM_Utils_Mail::setMimeParams($message); $h = $message->headers($headers); CRM_Mailing_BAO_Mailing::addMessageIdHeader($h, 'a', $eq->job_id, queue_id, $eq->hash); $mailer = $config->getMailer(); if (is_object($mailer)) { $errorScope = CRM_Core_TemporaryErrorScope::ignoreException(); $mailer->send($to, $h, $b); unset($errorScope); } }
/** * Create and Update mailing component * * @param array $params (reference ) an assoc array of name/value pairs * @param array $ids (reference ) the array that holds all the db ids * * @return object CRM_Mailing_BAO_Component object * * @access public * @static */ static function add(&$params, &$ids) { // action is taken depending upon the mode $component =& new CRM_Mailing_DAO_Component(); $component->name = $params['name']; $component->component_type = $params['component_type']; $component->subject = $params['subject']; if ($params['body_text']) { $component->body_text = $params['body_text']; } else { $component->body_text = CRM_Utils_String::htmlToText($params['body_html']); } $component->body_html = $params['body_html']; $component->is_active = CRM_Utils_Array::value('is_active', $params, false); $component->is_default = CRM_Utils_Array::value('is_default', $params, false); if ($component->is_default) { $query = "UPDATE civicrm_mailing_component SET is_default = 0 WHERE component_type ='{$component->component_type}'"; CRM_Core_DAO::executeQuery($query, CRM_Core_DAO::$_nullArray); } $component->id = CRM_Utils_Array::value('id', $ids); $component->save(); CRM_Core_Session::setStatus(ts('The mailing component \'%1\' has been saved.', array(1 => $component->name))); }
/** * Retrieve a ref to an array that holds the email and text templates for this email * assembles the complete template including the header and footer * that the user has uploaded or declared (if they have done that) * * @return array * reference to an assoc array */ private function &getTemplates() { if (!$this->templates) { $this->getHeaderFooter(); $this->templates = array(); if ($this->body_text || !empty($this->header)) { $template = array(); if (!empty($this->header->body_text)) { $template[] = $this->header->body_text; } elseif (!empty($this->header->body_html)) { $template[] = CRM_Utils_String::htmlToText($this->header->body_html); } if ($this->body_text) { $template[] = $this->body_text; } else { $template[] = CRM_Utils_String::htmlToText($this->body_html); } if (!empty($this->footer->body_text)) { $template[] = $this->footer->body_text; } elseif (!empty($this->footer->body_html)) { $template[] = CRM_Utils_String::htmlToText($this->footer->body_html); } $this->templates['text'] = implode("\n", $template); } // To check for an html part strip tags if (trim(strip_tags($this->body_html))) { $template = array(); if ($this->header) { $template[] = $this->header->body_html; } $template[] = $this->body_html; if ($this->footer) { $template[] = $this->footer->body_html; } $this->templates['html'] = implode("\n", $template); // this is where we create a text template from the html template if the text template did not exist // this way we ensure that every recipient will receive an email even if the pref is set to text and the // user uploads an html email only if (empty($this->templates['text'])) { $this->templates['text'] = CRM_Utils_String::htmlToText($this->templates['html']); } } if ($this->subject) { $template = array(); $template[] = $this->subject; $this->templates['subject'] = implode("\n", $template); } CRM_Utils_Hook::alterMailContent($this->templates); } return $this->templates; }
/** * Send an automated response * * @param object $mailing The mailing object * @param int $queue_id The queue ID * @param string $replyto Optional reply-to from the reply * @return void * @access private * @static */ private static function autoRespond(&$mailing, $queue_id, $replyto) { $config =& CRM_Core_Config::singleton(); $contacts = CRM_Contact_DAO_Contact::getTableName(); $email = CRM_Core_DAO_Email::getTableName(); $queue = CRM_Mailing_Event_DAO_Queue::getTableName(); $eq =& new CRM_Core_DAO(); $eq->query("SELECT {$contacts}.preferred_mail_format as format,\n {$email}.email as email\n FROM {$contacts}\n INNER JOIN {$queue} ON {$queue}.contact_id = {$contacts}.id\n INNER JOIN {$email} ON {$queue}.email_id = {$email}.id\n WHERE {$queue}.id = " . CRM_Utils_Type::escape($queue_id, 'Integer')); $eq->fetch(); $to = empty($replyto) ? $eq->email : $replyto; $component =& new CRM_Mailing_BAO_Component(); $component->id = $mailing->reply_id; $component->find(true); $message =& new Mail_Mime("\n"); require_once 'CRM/Core/BAO/Domain.php'; $domain =& CRM_Core_BAO_Domain::getDomain(); list($domainEmailName, $_) = CRM_Core_BAO_Domain::getNameAndEmail(); require_once 'CRM/Core/BAO/MailSettings.php'; $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $headers = array('Subject' => $component->subject, 'To' => $to, 'From' => "\"{$domainEmailName}\" <do-not-reply@{$emailDomain}>", 'Reply-To' => "do-not-reply@{$emailDomain}", 'Return-Path' => "do-not-reply@{$emailDomain}"); /* TODO: do we need reply tokens? */ $html = $component->body_html; if ($component->body_text) { $text = $component->body_text; } else { $text = CRM_Utils_String::htmlToText($component->body_html); } require_once 'CRM/Mailing/BAO/Mailing.php'; $bao =& new CRM_Mailing_BAO_Mailing(); $bao->body_text = $text; $bao->body_html = $html; $tokens = $bao->getTokens(); if ($eq->format == 'HTML' || $eq->format == 'Both') { require_once 'CRM/Utils/Token.php'; $html = CRM_Utils_Token::replaceDomainTokens($html, $domain, true, $tokens['html']); $html = CRM_Utils_Token::replaceMailingTokens($html, $mailing, null, $tokens['html']); $message->setHTMLBody($html); } if (!$html || $eq->format == 'Text' || $eq->format == 'Both') { require_once 'CRM/Utils/Token.php'; $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, false, $tokens['text']); $text = CRM_Utils_Token::replaceMailingTokens($text, $mailing, null, $tokens['text']); $message->setTxtBody($text); } $b =& CRM_Utils_Mail::setMimeParams($message); $h =& $message->headers($headers); $mailer =& $config->getMailer(); PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array('CRM_Core_Error', 'nullHandler')); if (is_object($mailer)) { $mailer->send($to, $h, $b); CRM_Core_Error::setCallback(); } }
/** * Ask a contact for subscription confirmation (opt-in) * * @param string $email * The email address. * * @return void */ public function send_confirm_request($email) { $config = CRM_Core_Config::singleton(); $domain = CRM_Core_BAO_Domain::getDomain(); //get the default domain email address. list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail(); $localpart = CRM_Core_BAO_MailSettings::defaultLocalpart(); $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $confirm = implode($config->verpSeparator, array($localpart . 'c', $this->contact_id, $this->id, $this->hash)) . "@{$emailDomain}"; $group = new CRM_Contact_BAO_Group(); $group->id = $this->group_id; $group->find(TRUE); $component = new CRM_Mailing_BAO_Component(); $component->is_default = 1; $component->is_active = 1; $component->component_type = 'Subscribe'; $component->find(TRUE); $headers = array('Subject' => $component->subject, 'From' => "\"{$domainEmailName}\" <{$domainEmailAddress}>", 'To' => $email, 'Reply-To' => $confirm, 'Return-Path' => "do-not-reply@{$emailDomain}"); $url = CRM_Utils_System::url('civicrm/mailing/confirm', "reset=1&cid={$this->contact_id}&sid={$this->id}&h={$this->hash}", TRUE); $html = $component->body_html; if ($component->body_text) { $text = $component->body_text; } else { $text = CRM_Utils_String::htmlToText($component->body_html); } $bao = new CRM_Mailing_BAO_Mailing(); $bao->body_text = $text; $bao->body_html = $html; $tokens = $bao->getTokens(); $html = CRM_Utils_Token::replaceDomainTokens($html, $domain, TRUE, $tokens['html']); $html = CRM_Utils_Token::replaceSubscribeTokens($html, $group->title, $url, TRUE); $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, FALSE, $tokens['text']); $text = CRM_Utils_Token::replaceSubscribeTokens($text, $group->title, $url, FALSE); // render the & entities in text mode, so that the links work $text = str_replace('&', '&', $text); $message = new Mail_mime("\n"); $message->setHTMLBody($html); $message->setTxtBody($text); $b = CRM_Utils_Mail::setMimeParams($message); $h = $message->headers($headers); CRM_Mailing_BAO_Mailing::addMessageIdHeader($h, 's', $this->contact_id, $this->id, $this->hash); $mailer = \Civi::service('pear_mail'); if (is_object($mailer)) { $errorScope = CRM_Core_TemporaryErrorScope::ignoreException(); $mailer->send($email, $h, $b); unset($errorScope); } }
static function sendReminder($contactId, $email, $messageTemplateID, $from) { require_once "CRM/Core/BAO/Domain.php"; require_once "CRM/Utils/String.php"; require_once "CRM/Utils/Token.php"; $messageTemplates =& new CRM_Core_DAO_MessageTemplates(); $messageTemplates->id = $messageTemplateID; $domain = CRM_Core_BAO_Domain::getDomain(); $result = null; if ($messageTemplates->find(true)) { $body_text = $messageTemplates->msg_text; $body_html = $messageTemplates->msg_html; $body_subject = $messageTemplates->msg_subject; if (!$body_text) { $body_text = CRM_Utils_String::htmlToText($body_html); } $params = array('contact_id' => $contactId); require_once 'api/v2/Contact.php'; $contact =& civicrm_contact_get($params); //CRM-4524 $contact = reset($contact); if (!$contact || is_a($contact, 'CRM_Core_Error')) { return null; } $type = array('html', 'text'); foreach ($type as $key => $value) { require_once 'CRM/Mailing/BAO/Mailing.php'; $dummy_mail = new CRM_Mailing_BAO_Mailing(); $bodyType = "body_{$value}"; $dummy_mail->{$bodyType} = ${$bodyType}; $tokens = $dummy_mail->getTokens(); if (${$bodyType}) { ${$bodyType} = CRM_Utils_Token::replaceDomainTokens(${$bodyType}, $domain, true, $tokens[$value]); ${$bodyType} = CRM_Utils_Token::replaceContactTokens(${$bodyType}, $contact, false, $tokens[$value]); } } $html = $body_html; $text = $body_text; $message =& new Mail_Mime("\n"); /* Do contact-specific token replacement in text mode, and add to the * message if necessary */ if (!$html || $contact['preferred_mail_format'] == 'Text' || $contact['preferred_mail_format'] == 'Both') { // render the & entities in text mode, so that the links work $text = str_replace('&', '&', $text); $message->setTxtBody($text); unset($text); } if ($html && ($contact['preferred_mail_format'] == 'HTML' || $contact['preferred_mail_format'] == 'Both')) { $message->setHTMLBody($html); unset($html); } $recipient = "\"{$contact['display_name']}\" <{$email}>"; $matches = array(); preg_match_all('/(?<!\\{|\\\\)\\{(\\w+\\.\\w+)\\}(?!\\})/', $body_subject, $matches, PREG_PATTERN_ORDER); $subjectToken = null; if ($matches[1]) { foreach ($matches[1] as $token) { list($type, $name) = split('\\.', $token, 2); if ($name) { if (!isset($subjectToken['contact'])) { $subjectToken['contact'] = array(); } $subjectToken['contact'][] = $name; } } } $messageSubject = CRM_Utils_Token::replaceContactTokens($body_subject, $contact, false, $subjectToken); $headers = array('From' => $from, 'Subject' => $messageSubject); $headers['To'] = $recipient; $mailMimeParams = array('text_encoding' => '8bit', 'html_encoding' => '8bit', 'head_charset' => 'utf-8', 'text_charset' => 'utf-8', 'html_charset' => 'utf-8'); $message->get($mailMimeParams); $message->headers($headers); $config =& CRM_Core_Config::singleton(); $mailer =& $config->getMailer(); $body = $message->get(); $headers = $message->headers(); CRM_Core_Error::ignoreException(); $result = $mailer->send($recipient, $headers, $body); CRM_Core_Error::setCallback(); } return $result; }
/** * Function for validation * * @param array $params (ref.) an assoc array of name/value pairs * * @param $files * @param $self * * @return mixed true or array of errors * @access public * @static */ static function formRule($params, $files, $self) { if (!empty($_POST['_qf_Import_refresh'])) { return TRUE; } $errors = array(); $template = CRM_Core_Smarty::singleton(); $domain = CRM_Core_BAO_Domain::getDomain(); $mailing = new CRM_Mailing_BAO_Mailing(); $mailing->id = $self->_mailingID; $mailing->find(TRUE); $session = CRM_Core_Session::singleton(); $values = array('contact_id' => $session->get('userID'), 'version' => 3); require_once 'api/api.php'; $contact = civicrm_api('contact', 'get', $values); //CRM-4524 $contact = reset($contact['values']); $verp = array_flip(array('optOut', 'reply', 'unsubscribe', 'resubscribe', 'owner')); foreach ($verp as $key => $value) { $verp[$key]++; } $urls = array_flip(array('forward', 'optOutUrl', 'unsubscribeUrl', 'resubscribeUrl')); foreach ($urls as $key => $value) { $urls[$key]++; } $skipTextFile = $self->get('skipTextFile'); if (!$params['upload_type']) { if (!isset($files['textFile']) || !file_exists($files['textFile']['tmp_name'])) { if (!$skipTextFile) { $errors['textFile'] = ts('Please provide a Text'); } } } else { if (empty($params['text_message'])) { $errors['text_message'] = ts('Please provide a Text'); } else { if (!empty($params['text_message'])) { $messageCheck = CRM_Utils_Array::value('text_message', $params); if ($messageCheck && strlen($messageCheck) > CRM_SMS_Provider::MAX_SMS_CHAR) { $errors['text_message'] = ts("You can configure the SMS message body up to %1 characters", array(1 => CRM_SMS_Provider::MAX_SMS_CHAR)); } } } if (!empty($params['saveTemplate']) && empty($params['saveTemplateName'])) { $errors['saveTemplateName'] = ts('Please provide a Template Name.'); } } if ($params['upload_type'] || file_exists(CRM_Utils_Array::value('tmp_name', $files['textFile'])) || !$params['upload_type'] && $params['text_message']) { if (!$params['upload_type']) { $str = file_get_contents($files['textFile']['tmp_name']); $name = $files['textFile']['name']; } else { $str = $params['text_message']; $name = 'text message'; } $dataErrors = array(); /* Do a full token replacement on a dummy verp, the current * contact and domain, and the first organization. */ // here we make a dummy mailing object so that we // can retrieve the tokens that we need to replace // so that we do get an invalid token error // this is qute hacky and I hope that there might // be a suggestion from someone on how to // make it a bit more elegant $dummy_mail = new CRM_Mailing_BAO_Mailing(); $mess = "body_text"; $dummy_mail->{$mess} = $str; $tokens = $dummy_mail->getTokens(); $str = CRM_Utils_Token::replaceSubscribeInviteTokens($str); $str = CRM_Utils_Token::replaceDomainTokens($str, $domain, NULL, $tokens['text']); $str = CRM_Utils_Token::replaceMailingTokens($str, $mailing, NULL, $tokens['text']); $str = CRM_Utils_Token::replaceOrgTokens($str, $org); $str = CRM_Utils_Token::replaceActionTokens($str, $verp, $urls, NULL, $tokens['text']); $str = CRM_Utils_Token::replaceContactTokens($str, $contact, NULL, $tokens['text']); $unmatched = CRM_Utils_Token::unmatchedTokens($str); $contentCheck = CRM_Utils_String::htmlToText($str); if (!empty($unmatched) && 0) { foreach ($unmatched as $token) { $dataErrors[] = '<li>' . ts('Invalid token code') . ' {' . $token . '}</li>'; } } if (strlen($contentCheck) > CRM_SMS_Provider::MAX_SMS_CHAR) { $dataErrors[] = '<li>' . ts('The body of the SMS cannot exceed %1 characters.', array(1 => CRM_SMS_Provider::MAX_SMS_CHAR)) . '</li>'; } if (!empty($dataErrors)) { $errors['textFile'] = ts('The following errors were detected in %1:', array(1 => $name)) . ' <ul>' . implode('', $dataErrors) . '</ul>'; } } $templateName = CRM_Core_BAO_MessageTemplate::getMessageTemplates(); if (!empty($params['saveTemplate']) && in_array(CRM_Utils_Array::value('saveTemplateName', $params), $templateName)) { $errors['saveTemplate'] = ts('Duplicate Template Name.'); } return empty($errors) ? TRUE : $errors; }
/** * Ask a contact for subscription confirmation (opt-in) * * @param string $email The email address * @return void * @access public */ public function send_confirm_request($email) { $config =& CRM_Core_Config::singleton(); require_once 'CRM/Core/BAO/Domain.php'; $domain =& CRM_Core_BAO_Domain::getDomain(); //get the default domain email address. list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail(); require_once 'CRM/Core/BAO/MailSettings.php'; $localpart = CRM_Core_BAO_MailSettings::defaultLocalpart(); $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); require_once 'CRM/Utils/Verp.php'; $confirm = implode($config->verpSeparator, array($localpart . 'c', $this->contact_id, $this->id, $this->hash)) . "@{$emailDomain}"; require_once 'CRM/Contact/BAO/Group.php'; $group =& new CRM_Contact_BAO_Group(); $group->id = $this->group_id; $group->find(true); require_once 'CRM/Mailing/BAO/Component.php'; $component =& new CRM_Mailing_BAO_Component(); $component->is_default = 1; $component->is_active = 1; $component->component_type = 'Subscribe'; $component->find(true); $headers = array('Subject' => $component->subject, 'From' => "\"{$domainEmailName}\" <{$domainEmailAddress}>", 'To' => $email, 'Reply-To' => $confirm, 'Return-Path' => "do-not-reply@{$emailDomain}"); $url = CRM_Utils_System::url('civicrm/mailing/confirm', "reset=1&cid={$this->contact_id}&sid={$this->id}&h={$this->hash}", true); $html = $component->body_html; if ($component->body_text) { $text = $component->body_text; } else { $text = CRM_Utils_String::htmlToText($component->body_html); } require_once 'CRM/Mailing/BAO/Mailing.php'; $bao =& new CRM_Mailing_BAO_Mailing(); $bao->body_text = $text; $bao->body_html = $html; $tokens = $bao->getTokens(); require_once 'CRM/Utils/Token.php'; $html = CRM_Utils_Token::replaceDomainTokens($html, $domain, true, $tokens['html']); $html = CRM_Utils_Token::replaceSubscribeTokens($html, $group->title, $url, true); $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, false, $tokens['text']); $text = CRM_Utils_Token::replaceSubscribeTokens($text, $group->title, $url, false); // render the & entities in text mode, so that the links work $text = str_replace('&', '&', $text); // we need to wrap Mail_mime because PEAR is apparently unable to fix // a six-year-old bug (PEAR bug #30) in Mail_mime::_encodeHeaders() // this fixes CRM-5466 require_once 'CRM/Utils/Mail/FixedMailMIME.php'; $message =& new CRM_Utils_Mail_FixedMailMIME("\n"); $message->setHTMLBody($html); $message->setTxtBody($text); $b =& CRM_Utils_Mail::setMimeParams($message); $h =& $message->headers($headers); $mailer =& $config->getMailer(); require_once 'CRM/Mailing/BAO/Mailing.php'; PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array('CRM_Core_Error', 'nullHandler')); if (is_object($mailer)) { $mailer->send($email, $h, $b); CRM_Core_Error::setCallback(); } }
/** * Send a reponse email informing the contact of the groups from which he * has been unsubscribed. * * @param string $queue_id The queue event ID * @param array $groups List of group IDs * @param bool $is_domain Is this domain-level? * @param int $job The job ID * @return void * @access public * @static */ public static function send_unsub_response($queue_id, $groups, $is_domain = false, $job) { $config =& CRM_Core_Config::singleton(); $domain =& CRM_Core_BAO_Domain::getDomain(); $jobTable = CRM_Mailing_BAO_Job::getTableName(); $mailingTable = CRM_Mailing_DAO_Mailing::getTableName(); $contacts = CRM_Contact_DAO_Contact::getTableName(); $email = CRM_Core_DAO_Email::getTableName(); $queue = CRM_Mailing_Event_BAO_Queue::getTableName(); //get the default domain email address. list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail(); $dao =& new CRM_Mailing_BAO_Mailing(); $dao->query(" SELECT * FROM {$mailingTable} \n INNER JOIN {$jobTable} ON\n {$jobTable}.mailing_id = {$mailingTable}.id \n WHERE {$jobTable}.id = {$job}"); $dao->fetch(); $component =& new CRM_Mailing_BAO_Component(); if ($is_domain) { $component->id = $dao->optout_id; } else { $component->id = $dao->unsubscribe_id; } $component->find(true); $html = $component->body_html; if ($component->body_text) { $text = $component->body_text; } else { $text = CRM_Utils_String::htmlToText($component->body_html); } $eq =& new CRM_Core_DAO(); $eq->query("SELECT {$contacts}.preferred_mail_format as format,\n {$contacts}.id as contact_id,\n {$email}.email as email,\n {$queue}.hash as hash\n FROM {$contacts}\n INNER JOIN {$queue} ON {$queue}.contact_id = {$contacts}.id\n INNER JOIN {$email} ON {$queue}.email_id = {$email}.id\n WHERE {$queue}.id = " . CRM_Utils_Type::escape($queue_id, 'Integer')); $eq->fetch(); if ($groups) { foreach ($groups as $key => $value) { if (!$value) { unset($groups[$key]); } } } $message =& new Mail_Mime("\n"); list($addresses, $urls) = CRM_Mailing_BAO_Mailing::getVerpAndUrls($job, $queue_id, $eq->hash, $eq->email); $bao =& new CRM_Mailing_BAO_Mailing(); $bao->body_text = $text; $bao->body_html = $html; $tokens = $bao->getTokens(); require_once 'CRM/Utils/Token.php'; if ($eq->format == 'HTML' || $eq->format == 'Both') { $html = CRM_Utils_Token::replaceDomainTokens($html, $domain, true, $tokens['html']); $html = CRM_Utils_Token::replaceUnsubscribeTokens($html, $domain, $groups, true, $eq->contact_id, $eq->hash); $html = CRM_Utils_Token::replaceActionTokens($html, $addresses, $urls, true, $tokens['html']); $html = CRM_Utils_Token::replaceMailingTokens($html, $dao, null, $tokens['html']); $message->setHTMLBody($html); } if (!$html || $eq->format == 'Text' || $eq->format == 'Both') { $text = CRM_Utils_Token::replaceDomainTokens($text, $domain, false, $tokens['text']); $text = CRM_Utils_Token::replaceUnsubscribeTokens($text, $domain, $groups, false, $eq->contact_id, $eq->hash); $text = CRM_Utils_Token::replaceActionTokens($text, $addresses, $urls, false, $tokens['text']); $text = CRM_Utils_Token::replaceMailingTokens($text, $dao, null, $tokens['text']); $message->setTxtBody($text); } require_once 'CRM/Core/BAO/MailSettings.php'; $emailDomain = CRM_Core_BAO_MailSettings::defaultDomain(); $headers = array('Subject' => $component->subject, 'From' => "\"{$domainEmailName}\" <do-not-reply@{$emailDomain}>", 'To' => $eq->email, 'Reply-To' => "do-not-reply@{$emailDomain}", 'Return-Path' => "do-not-reply@{$emailDomain}"); $b =& CRM_Utils_Mail::setMimeParams($message); $h =& $message->headers($headers); $mailer =& $config->getMailer(); PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array('CRM_Core_Error', 'nullHandler')); if (is_object($mailer)) { $mailer->send($eq->email, $h, $b); CRM_Core_Error::setCallback(); } }
/** * @param int $contactId * @param $email * @param int $messageTemplateID * @param $from * * @return bool|NULL */ public static function sendReminder($contactId, $email, $messageTemplateID, $from) { $messageTemplates = new CRM_Core_DAO_MessageTemplate(); $messageTemplates->id = $messageTemplateID; $domain = CRM_Core_BAO_Domain::getDomain(); $result = NULL; $hookTokens = array(); if ($messageTemplates->find(TRUE)) { $body_text = $messageTemplates->msg_text; $body_html = $messageTemplates->msg_html; $body_subject = $messageTemplates->msg_subject; if (!$body_text) { $body_text = CRM_Utils_String::htmlToText($body_html); } $params = array(array('contact_id', '=', $contactId, 0, 0)); list($contact, $_) = CRM_Contact_BAO_Query::apiQuery($params); //CRM-4524 $contact = reset($contact); if (!$contact || is_a($contact, 'CRM_Core_Error')) { return NULL; } //CRM-5734 // get tokens to be replaced $tokens = array_merge(CRM_Utils_Token::getTokens($body_text), CRM_Utils_Token::getTokens($body_html), CRM_Utils_Token::getTokens($body_subject)); // get replacement text for these tokens $returnProperties = array("preferred_mail_format" => 1); if (isset($tokens['contact'])) { foreach ($tokens['contact'] as $key => $value) { $returnProperties[$value] = 1; } } list($details) = CRM_Utils_Token::getTokenDetails(array($contactId), $returnProperties, NULL, NULL, FALSE, $tokens, 'CRM_Core_BAO_MessageTemplate'); $contact = reset($details); // call token hook $hookTokens = array(); CRM_Utils_Hook::tokens($hookTokens); $categories = array_keys($hookTokens); // do replacements in text and html body $type = array('html', 'text'); foreach ($type as $key => $value) { $bodyType = "body_{$value}"; if (${$bodyType}) { CRM_Utils_Token::replaceGreetingTokens(${$bodyType}, NULL, $contact['contact_id']); ${$bodyType} = CRM_Utils_Token::replaceDomainTokens(${$bodyType}, $domain, TRUE, $tokens, TRUE); ${$bodyType} = CRM_Utils_Token::replaceContactTokens(${$bodyType}, $contact, FALSE, $tokens, FALSE, TRUE); ${$bodyType} = CRM_Utils_Token::replaceComponentTokens(${$bodyType}, $contact, $tokens, TRUE); ${$bodyType} = CRM_Utils_Token::replaceHookTokens(${$bodyType}, $contact, $categories, TRUE); } } $html = $body_html; $text = $body_text; $smarty = CRM_Core_Smarty::singleton(); foreach (array('text', 'html') as $elem) { ${$elem} = $smarty->fetch("string:{${$elem}}"); } // do replacements in message subject $messageSubject = CRM_Utils_Token::replaceContactTokens($body_subject, $contact, FALSE, $tokens); $messageSubject = CRM_Utils_Token::replaceDomainTokens($messageSubject, $domain, TRUE, $tokens); $messageSubject = CRM_Utils_Token::replaceComponentTokens($messageSubject, $contact, $tokens, TRUE); $messageSubject = CRM_Utils_Token::replaceHookTokens($messageSubject, $contact, $categories, TRUE); $messageSubject = $smarty->fetch("string:{$messageSubject}"); // set up the parameters for CRM_Utils_Mail::send $mailParams = array('groupName' => 'Scheduled Reminder Sender', 'from' => $from, 'toName' => $contact['display_name'], 'toEmail' => $email, 'subject' => $messageSubject); if (!$html || $contact['preferred_mail_format'] == 'Text' || $contact['preferred_mail_format'] == 'Both') { // render the & entities in text mode, so that the links work $mailParams['text'] = str_replace('&', '&', $text); } if ($html && ($contact['preferred_mail_format'] == 'HTML' || $contact['preferred_mail_format'] == 'Both')) { $mailParams['html'] = $html; } $result = CRM_Utils_Mail::send($mailParams); } $messageTemplates->free(); return $result; }
/** * @param $contactId * @param $to * @param $scheduleID * @param $from * @param $tokenParams * * @return bool|null * @throws CRM_Core_Exception */ static function sendReminder($contactId, $to, $scheduleID, $from, $tokenParams) { $email = $to['email']; $phoneNumber = $to['phone']; $schedule = new CRM_Core_DAO_ActionSchedule(); $schedule->id = $scheduleID; $domain = CRM_Core_BAO_Domain::getDomain(); $result = NULL; $hookTokens = array(); if ($schedule->find(TRUE)) { $body_text = $schedule->body_text; $body_html = $schedule->body_html; $sms_body_text = $schedule->sms_body_text; $body_subject = $schedule->subject; if (!$body_text) { $body_text = CRM_Utils_String::htmlToText($body_html); } $params = array(array('contact_id', '=', $contactId, 0, 0)); list($contact, $_) = CRM_Contact_BAO_Query::apiQuery($params); //CRM-4524 $contact = reset($contact); if (!$contact || is_a($contact, 'CRM_Core_Error')) { return NULL; } // merge activity tokens with contact array $contact = array_merge($contact, $tokenParams); //CRM-5734 CRM_Utils_Hook::tokenValues($contact, $contactId); CRM_Utils_Hook::tokens($hookTokens); $categories = array_keys($hookTokens); $type = array('body_html' => 'html', 'body_text' => 'text', 'sms_body_text' => 'text'); foreach ($type as $bodyType => $value) { $dummy_mail = new CRM_Mailing_BAO_Mailing(); if ($bodyType == 'sms_body_text') { $dummy_mail->body_text = ${$bodyType}; } else { $dummy_mail->{${$bodyType}} = ${$bodyType}; } $tokens = $dummy_mail->getTokens(); if (${$bodyType}) { CRM_Utils_Token::replaceGreetingTokens(${$bodyType}, NULL, $contact['contact_id']); ${$bodyType} = CRM_Utils_Token::replaceDomainTokens(${$bodyType}, $domain, TRUE, $tokens[$value], TRUE); ${$bodyType} = CRM_Utils_Token::replaceContactTokens(${$bodyType}, $contact, FALSE, $tokens[$value], FALSE, TRUE); ${$bodyType} = CRM_Utils_Token::replaceComponentTokens(${$bodyType}, $contact, $tokens[$value], TRUE, FALSE); ${$bodyType} = CRM_Utils_Token::replaceHookTokens(${$bodyType}, $contact, $categories, TRUE); } } $html = $body_html; $text = $body_text; $sms_text = $sms_body_text; $smarty = CRM_Core_Smarty::singleton(); foreach (array('text', 'html', 'sms_text') as $elem) { ${$elem} = $smarty->fetch("string:{${$elem}}"); } $matches = array(); preg_match_all('/(?<!\\{|\\\\)\\{(\\w+\\.\\w+)\\}(?!\\})/', $body_subject, $matches, PREG_PATTERN_ORDER); $subjectToken = NULL; if ($matches[1]) { foreach ($matches[1] as $token) { list($type, $name) = preg_split('/\\./', $token, 2); if ($name) { if (!isset($subjectToken[$type])) { $subjectToken[$type] = array(); } $subjectToken[$type][] = $name; } } } $messageSubject = CRM_Utils_Token::replaceContactTokens($body_subject, $contact, FALSE, $subjectToken); $messageSubject = CRM_Utils_Token::replaceDomainTokens($messageSubject, $domain, TRUE, $subjectToken); $messageSubject = CRM_Utils_Token::replaceComponentTokens($messageSubject, $contact, $subjectToken, TRUE); $messageSubject = CRM_Utils_Token::replaceHookTokens($messageSubject, $contact, $categories, TRUE); $messageSubject = $smarty->fetch("string:{$messageSubject}"); if ($schedule->mode == 'SMS' or $schedule->mode == 'User_Preference') { $session = CRM_Core_Session::singleton(); $userID = $session->get('userID') ? $session->get('userID') : $contactId; $smsParams = array('To' => $phoneNumber, 'provider_id' => $schedule->sms_provider_id, 'activity_subject' => $messageSubject); $activityTypeID = CRM_Core_OptionGroup::getValue('activity_type', 'SMS', 'name'); $activityParams = array('source_contact_id' => $userID, 'activity_type_id' => $activityTypeID, 'activity_date_time' => date('YmdHis'), 'subject' => $messageSubject, 'details' => $sms_text, 'status_id' => CRM_Core_OptionGroup::getValue('activity_status', 'Completed', 'name')); $activity = CRM_Activity_BAO_Activity::create($activityParams); CRM_Activity_BAO_Activity::sendSMSMessage($contactId, $sms_text, $html, $smsParams, $activity->id, $userID); } if ($schedule->mode == 'Email' or $schedule->mode == 'User_Preference') { // set up the parameters for CRM_Utils_Mail::send $mailParams = array('groupName' => 'Scheduled Reminder Sender', 'from' => $from, 'toName' => $contact['display_name'], 'toEmail' => $email, 'subject' => $messageSubject, 'entity' => 'action_schedule', 'entity_id' => $scheduleID); if (!$html || $contact['preferred_mail_format'] == 'Text' || $contact['preferred_mail_format'] == 'Both') { // render the & entities in text mode, so that the links work $mailParams['text'] = str_replace('&', '&', $text); } if ($html && ($contact['preferred_mail_format'] == 'HTML' || $contact['preferred_mail_format'] == 'Both')) { $mailParams['html'] = $html; } $result = CRM_Utils_Mail::send($mailParams); } } $schedule->free(); return $result; }
/** * Create and Update mailing component * * @param array $params (reference ) an assoc array of name/value pairs * @param array $ids (deprecated) the array that holds all the db ids * * @return object CRM_Mailing_BAO_Component object * * @access public * @static */ static function add(&$params, $ids = array()) { $id = CRM_Utils_Array::value('id', $params, CRM_Utils_Array::value('id', $ids)); $component = new CRM_Mailing_DAO_Component(); $component->id = $id; $component->copyValues($params); if (empty($id) && empty($params['body_text'])) { $component->body_text = CRM_Utils_String::htmlToText(CRM_Utils_Array::value('body_html', $params)); } if ($component->is_default && !empty($id)) { CRM_Core_DAO::executeQuery("UPDATE civicrm_mailing_component SET is_default = 0 WHERE component_type ='{$component->component_type}' AND id <> {$id}"); } $component->save(); return $component; }
/** * Create and Update mailing component. * * @param array $params * (reference ) an assoc array of name/value pairs. * @param array $ids * (deprecated) the array that holds all the db ids. * * @return CRM_Mailing_BAO_Component * */ public static function add(&$params, $ids = array()) { $id = CRM_Utils_Array::value('id', $params, CRM_Utils_Array::value('id', $ids)); $component = new CRM_Mailing_DAO_Component(); if ($id) { $component->id = $id; $component->find(TRUE); } $component->copyValues($params); if (empty($id) && empty($params['body_text'])) { $component->body_text = CRM_Utils_String::htmlToText(CRM_Utils_Array::value('body_html', $params)); } if ($component->is_default) { if (!empty($id)) { $sql = 'UPDATE civicrm_mailing_component SET is_default = 0 WHERE component_type = %1 AND id <> %2'; $sqlParams = array(1 => array($component->component_type, 'String'), 2 => array($id, 'Positive')); } else { $sql = 'UPDATE civicrm_mailing_component SET is_default = 0 WHERE component_type = %1'; $sqlParams = array(1 => array($component->component_type, 'String')); } CRM_Core_DAO::executeQuery($sql, $sqlParams); } $component->save(); return $component; }
/** * 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) { require_once 'CRM/Core/BAO/MailSettings.php'; $returnPath = CRM_Core_BAO_MailSettings::defaultReturnPath(); $from = CRM_Utils_Array::value('from', $params); if (!$returnPath) { $returnPath = self::pluckEmailFromHeader($from); } $params['returnPath'] = $returnPath; // first call the mail alter hook require_once 'CRM/Utils/Hook.php'; 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(); $headers['From'] = $params['from']; $headers['To'] = "{$params['toName']} <{$params['toEmail']}>"; $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); $headers['Reply-To'] = CRM_Utils_Array::value('replyTo', $params, $from); $headers['Date'] = date('r'); 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) { $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']); if (substr($from[0], 0, 1) != '"' || substr($from[0], -1, 1) != '"') { $from[0] = str_replace('"', '\\"', $from[0]); $headers['From'] = "\"{$from[0]}\" <{$from[1]}"; } } 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); CRM_Core_Session::setStatus($message, false); return false; } return true; } return false; }