PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/drupal/sites/all/modules/civicrm/CRM/Utils/Mail.php

https://github.com/michaelmcandrew/lbc
PHP | 343 lines | 219 code | 36 blank | 88 comment | 52 complexity | e362a42813954166c336812801e26340 MD5 | raw file
  1. <?php
  2. /*
  3. +--------------------------------------------------------------------+
  4. | CiviCRM version 4.1 |
  5. +--------------------------------------------------------------------+
  6. | Copyright CiviCRM LLC (c) 2004-2011 |
  7. +--------------------------------------------------------------------+
  8. | This file is a part of CiviCRM. |
  9. | |
  10. | CiviCRM is free software; you can copy, modify, and distribute it |
  11. | under the terms of the GNU Affero General Public License |
  12. | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
  13. | |
  14. | CiviCRM is distributed in the hope that it will be useful, but |
  15. | WITHOUT ANY WARRANTY; without even the implied warranty of |
  16. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
  17. | See the GNU Affero General Public License for more details. |
  18. | |
  19. | You should have received a copy of the GNU Affero General Public |
  20. | License and the CiviCRM Licensing Exception along |
  21. | with this program; if not, contact CiviCRM LLC |
  22. | at info[AT]civicrm[DOT]org. If you have questions about the |
  23. | GNU Affero General Public License or the licensing of CiviCRM, |
  24. | see the CiviCRM license FAQ at http://civicrm.org/licensing |
  25. +--------------------------------------------------------------------+
  26. */
  27. /**
  28. *
  29. * @package CRM
  30. * @copyright CiviCRM LLC (c) 2004-2011
  31. * $Id$
  32. *
  33. */
  34. class CRM_Utils_Mail
  35. {
  36. /**
  37. * Wrapper function to send mail in CiviCRM. Hooks are called from this function. The input parameter
  38. * is an associateive array which holds the values of field needed to send an email. These are:
  39. *
  40. * from : complete from envelope
  41. * toName : name of person to send email
  42. * toEmail : email address to send to
  43. * cc : email addresses to cc
  44. * bcc : email addresses to bcc
  45. * subject : subject of the email
  46. * text : text of the message
  47. * html : html version of the message
  48. * replyTo : reply-to header in the email
  49. * attachments: an associative array of
  50. * fullPath : complete pathname to the file
  51. * mime_type: mime type of the attachment
  52. * cleanName: the user friendly name of the attachmment
  53. *
  54. * @param array $params (by reference)
  55. *
  56. * @access public
  57. * @return boolean true if a mail was sent, else false
  58. */
  59. static function send( &$params ) {
  60. require_once 'CRM/Core/BAO/MailSettings.php';
  61. $returnPath = CRM_Core_BAO_MailSettings::defaultReturnPath();
  62. $from = CRM_Utils_Array::value( 'from', $params );
  63. if ( ! $returnPath ) {
  64. $returnPath = self::pluckEmailFromHeader($from);
  65. }
  66. $params['returnPath'] = $returnPath;
  67. // first call the mail alter hook
  68. require_once 'CRM/Utils/Hook.php';
  69. CRM_Utils_Hook::alterMailParams( $params );
  70. // check if any module has aborted mail sending
  71. if ( CRM_Utils_Array::value( 'abortMailSend', $params ) ||
  72. ! CRM_Utils_Array::value( 'toEmail', $params ) ) {
  73. return false;
  74. }
  75. $textMessage = CRM_Utils_Array::value( 'text' , $params );
  76. $htmlMessage = CRM_Utils_Array::value( 'html' , $params );
  77. $attachments = CRM_Utils_Array::value( 'attachments', $params );
  78. // CRM-6224
  79. require_once 'CRM/Utils/String.php';
  80. if (trim(CRM_Utils_String::htmlToText($htmlMessage)) == '') {
  81. $htmlMessage = false;
  82. }
  83. $headers = array( );
  84. $headers['From'] = $params['from'];
  85. $headers['To'] = self::formatRFC822Email( CRM_Utils_Array::value( 'toName', $params ),
  86. CRM_Utils_Array::value( 'toEmail', $params ),
  87. false );
  88. $headers['Cc'] = CRM_Utils_Array::value( 'cc', $params );
  89. $headers['Bcc'] = CRM_Utils_Array::value( 'bcc', $params );
  90. $headers['Subject'] = CRM_Utils_Array::value( 'subject', $params );
  91. $headers['Content-Type'] = $htmlMessage ? 'multipart/mixed; charset=utf-8' : 'text/plain; charset=utf-8';
  92. $headers['Content-Disposition'] = 'inline';
  93. $headers['Content-Transfer-Encoding'] = '8bit';
  94. $headers['Return-Path'] = CRM_Utils_Array::value( 'returnPath', $params );
  95. $headers['Reply-To'] = CRM_Utils_Array::value( 'replyTo', $params, $from );
  96. $headers['Date'] = date('r');
  97. if (CRM_Utils_Array::value( 'autoSubmitted', $params )) {
  98. $headers['Auto-Submitted'] = "Auto-Generated";
  99. }
  100. //make sure we has to have space, CRM-6977
  101. foreach ( array( 'From', 'To', 'Cc', 'Bcc', 'Reply-To', 'Return-Path' ) as $fld ) {
  102. $headers[$fld] = str_replace( '"<', '" <', $headers[$fld] );
  103. }
  104. // quote FROM, if comma is detected AND is not already quoted. CRM-7053
  105. if ( strpos( $headers['From'], ',' ) !== false ) {
  106. $from = explode( ' <', $headers['From'] );
  107. $headers['From'] = self::formatRFC822Email( $from[0],
  108. substr( $from[1], 0, -1 ),
  109. true );
  110. }
  111. require_once 'Mail/mime.php';
  112. $msg = new Mail_mime("\n");
  113. if ( $textMessage ) {
  114. $msg->setTxtBody($textMessage);
  115. }
  116. if ( $htmlMessage ) {
  117. $msg->setHTMLBody($htmlMessage);
  118. }
  119. if ( ! empty( $attachments ) ) {
  120. foreach ( $attachments as $fileID => $attach ) {
  121. $msg->addAttachment( $attach['fullPath'],
  122. $attach['mime_type'],
  123. $attach['cleanName'] );
  124. }
  125. }
  126. $message = self::setMimeParams( $msg );
  127. $headers =& $msg->headers($headers);
  128. $to = array( $params['toEmail'] );
  129. //get emails from headers, since these are
  130. //combination of name and email addresses.
  131. if ( CRM_Utils_Array::value( 'Cc', $headers ) ) {
  132. $to[] = CRM_Utils_Array::value( 'Cc', $headers );
  133. }
  134. if ( CRM_Utils_Array::value( 'Bcc', $headers ) ) {
  135. $to[] = CRM_Utils_Array::value( 'Bcc', $headers );
  136. unset( $headers['Bcc'] );
  137. }
  138. $result = null;
  139. $mailer = CRM_Core_Config::getMailer( );
  140. CRM_Core_Error::ignoreException( );
  141. if ( is_object( $mailer ) ) {
  142. $result = $mailer->send($to, $headers, $message);
  143. CRM_Core_Error::setCallback();
  144. if ( is_a( $result, 'PEAR_Error' ) ) {
  145. $message = self::errorMessage ($mailer, $result );
  146. CRM_Core_Session::setStatus( $message, false );
  147. return false;
  148. }
  149. return true;
  150. }
  151. return false;
  152. }
  153. static function errorMessage( $mailer, $result ) {
  154. $message =
  155. '<p>' . ts('An error occurred when CiviCRM attempted to send an email (via %1). If you received this error after submitting on online contribution or event registration - the transaction was completed, but we were unable to send the email receipt.', array(1 => 'SMTP')) . '</p>' .
  156. '<p>' . ts('The mail library returned the following error message:') . '<br /><span class="font-red"><strong>' . $result->getMessage() . '</strong></span></p>' .
  157. '<p>' . ts('This is probably related to a problem in your Outbound Email Settings (Administer CiviCRM &raquo; Global Settings &raquo; Outbound Email), OR the FROM email address specifically configured for your contribution page or event. Possible causes are:') . '</p>';
  158. if ( is_a( $mailer , 'Mail_smtp' ) ) {
  159. $message .=
  160. '<ul>' .
  161. '<li>' . ts('Your SMTP Username or Password are incorrect.') . '</li>' .
  162. '<li>' . ts('Your SMTP Server (machine) name is incorrect.') . '</li>' .
  163. '<li>' . ts('You need to use a Port other than the default port 25 in your environment.') . '</li>' .
  164. '<li>' . ts('Your SMTP server is just not responding right now (it is down for some reason).') . '</li>';
  165. } else {
  166. $message .=
  167. '<ul>' .
  168. '<li>' . ts('Your Sendmail path is incorrect.') . '</li>' .
  169. '<li>' . ts('Your Sendmail argument is incorrect.') . '</li>';
  170. }
  171. $message .=
  172. '<li>' . ts('The FROM Email Address configured for this feature may not be a valid sender based on your email service provider rules.') . '</li>' .
  173. '</ul>' .
  174. '<p>' . ts('Check <a href="%1">this page</a> for more information.', array(1 => CRM_Utils_System::docURL2('Outbound Email (SMTP)', true))) . '</p>';
  175. return $message;
  176. }
  177. function logger( &$to, &$headers, &$message ) {
  178. if ( is_array( $to ) ) {
  179. $toString = implode( ', ', $to );
  180. $fileName = $to[0];
  181. } else {
  182. $toString = $fileName = $to;
  183. }
  184. $content = "To: " . $toString . "\n";
  185. foreach ( $headers as $key => $val ) {
  186. $content .= "$key: $val\n";
  187. }
  188. $content .= "\n" . $message . "\n";
  189. if ( is_numeric( CIVICRM_MAIL_LOG ) ) {
  190. $config = CRM_Core_Config::singleton( );
  191. // create the directory if not there
  192. $dirName = $config->configAndLogDir . 'mail' . DIRECTORY_SEPARATOR;
  193. CRM_Utils_File::createDir( $dirName );
  194. $fileName = md5( uniqid( CRM_Utils_String::munge( $fileName ) ) ) . '.txt';
  195. file_put_contents( $dirName . $fileName,
  196. $content );
  197. } else {
  198. file_put_contents( CIVICRM_MAIL_LOG, $content, FILE_APPEND );
  199. }
  200. }
  201. /**
  202. * Get the email address itself from a formatted full name + address string
  203. *
  204. * Ugly but working.
  205. *
  206. * @param string $header the full name + email address string
  207. * @return string the plucked email address
  208. */
  209. function pluckEmailFromHeader($header) {
  210. preg_match('/<([^<]*)>$/', $header, $matches);
  211. if ( isset($matches[1]) ) {
  212. return $matches[1];
  213. }
  214. return null;
  215. }
  216. /**
  217. * Get the Active outBound email
  218. * @return boolean true if valid outBound email configuration found, false otherwise
  219. * @access public
  220. * @static
  221. */
  222. static function validOutBoundMail() {
  223. require_once 'CRM/Core/BAO/Setting.php';
  224. $mailingInfo = CRM_Core_BAO_Setting::getItem( CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME,
  225. 'mailing_backend' );
  226. if ( $mailingInfo['outBound_option'] == 3 ) {
  227. return true;
  228. } else if ( $mailingInfo['outBound_option'] == 0 ) {
  229. if ( !isset( $mailingInfo['smtpServer'] ) || $mailingInfo['smtpServer'] == '' ||
  230. $mailingInfo['smtpServer'] == 'YOUR SMTP SERVER'||
  231. ( $mailingInfo['smtpAuth'] && ( $mailingInfo['smtpUsername'] == '' || $mailingInfo['smtpPassword'] == '' ) ) ) {
  232. return false;
  233. }
  234. return true;
  235. } else if ( $mailingInfo['outBound_option'] == 1 ) {
  236. if ( ! $mailingInfo['sendmail_path'] || ! $mailingInfo['sendmail_args'] ) {
  237. return false;
  238. }
  239. return true;
  240. }
  241. return false;
  242. }
  243. static function &setMimeParams( &$message, $params = null ) {
  244. static $mimeParams = null;
  245. if ( ! $params ) {
  246. if ( ! $mimeParams ) {
  247. $mimeParams = array(
  248. 'text_encoding' => '8bit',
  249. 'html_encoding' => '8bit',
  250. 'head_charset' => 'utf-8',
  251. 'text_charset' => 'utf-8',
  252. 'html_charset' => 'utf-8',
  253. );
  254. }
  255. $params = $mimeParams;
  256. }
  257. return $message->get( $params );
  258. }
  259. static function formatRFC822Email( $name, $email, $useQuote = false ) {
  260. $result = null;
  261. $name = trim( $name );
  262. // strip out double quotes if present at the beginning AND end
  263. if ( substr( $name, 0, 1 ) == '"' &&
  264. substr( $name, -1, 1 ) == '"' ) {
  265. $name = substr( $name, 1, -1 );
  266. }
  267. if ( ! empty( $name ) ) {
  268. // escape the special characters
  269. $name = str_replace( array( '<' , '"' , '>' ),
  270. array( '\<', '\"', '\>' ),
  271. $name );
  272. if ( strpos( $name, ',' ) !== false ||
  273. $useQuote ) {
  274. // quote the string if it has a comma
  275. $name = '"' . $name . '"';
  276. }
  277. $result = "$name ";
  278. }
  279. $result .= "<{$email}>";
  280. return $result;
  281. }
  282. /**
  283. * Takes a string and checks to see if it needs to be escaped / double quoted
  284. * and if so does the needful and return the formatted name
  285. *
  286. * This code has been copied and adapted from ezc/Mail/src/tools.php
  287. */
  288. static function formatRFC2822Name( $name )
  289. {
  290. $name = trim( $name );
  291. if ( ! empty( $name ) ) {
  292. // remove the quotes around the name part if they are already there
  293. if ( substr( $name, 0, 1 ) == '"' && substr( $name, -1 ) == '"' ) {
  294. $name = substr( $name, 1, -1 );
  295. }
  296. // add slashes to " and \ and surround the name part with quotes
  297. if ( strpbrk( $name, ",@<>:;'\"" ) !== false ) {
  298. $name = '"'. addcslashes( $name, '\\"' ) . '"';
  299. }
  300. }
  301. return $name;
  302. }
  303. }