Open Monograph Press  3.3.0
Mail.inc.php
1 <?php
2 
21 define('MAIL_WRAP', 76);
22 
23 class Mail extends DataObject {
25  var $privateParams;
26 
30  function __construct() {
31  parent::__construct();
32  $this->privateParams = array();
33  if (Config::getVar('email', 'allow_envelope_sender')) {
34  $defaultEnvelopeSender = Config::getVar('email', 'default_envelope_sender');
35  if (!empty($defaultEnvelopeSender)) $this->setEnvelopeSender($defaultEnvelopeSender);
36  }
37  }
38 
43  function addPrivateParam($name, $value) {
44  $this->privateParams[$name] = $value;
45  }
46 
52  $this->privateParams = $privateParams;
53  }
54 
60  function addRecipient($email, $name = '') {
61  if (($recipients = $this->getData('recipients')) == null) {
62  $recipients = array();
63  }
64  array_push($recipients, array('name' => $name, 'email' => $email));
65 
66  $this->setData('recipients', $recipients);
67  }
68 
74  function setEnvelopeSender($envelopeSender) {
75  $this->setData('envelopeSender', $envelopeSender);
76  }
77 
83  function getEnvelopeSender() {
84  if (Config::getVar('email', 'force_default_envelope_sender') && Config::getVar('email', 'default_envelope_sender')) {
85  return Config::getVar('email', 'default_envelope_sender');
86  } else {
87  return $this->getData('envelopeSender');
88  }
89  }
90 
91 
96  function getContentType() {
97  return $this->getData('content_type');
98  }
99 
104  function setContentType($contentType) {
105  $this->setData('content_type', $contentType);
106  }
107 
112  function getRecipients() {
113  return $this->getData('recipients');
114  }
115 
120  function setRecipients($recipients) {
121  $this->setData('recipients', $recipients);
122  }
123 
129  function addCc($email, $name = '') {
130  if (($ccs = $this->getData('ccs')) == null) {
131  $ccs = array();
132  }
133  array_push($ccs, array('name' => $name, 'email' => $email));
134 
135  $this->setData('ccs', $ccs);
136  }
137 
142  function getCcs() {
143  return $this->getData('ccs');
144  }
145 
150  function setCcs($ccs) {
151  $this->setData('ccs', $ccs);
152  }
153 
159  function addBcc($email, $name = '') {
160  if (($bccs = $this->getData('bccs')) == null) {
161  $bccs = array();
162  }
163  array_push($bccs, array('name' => $name, 'email' => $email));
164 
165  $this->setData('bccs', $bccs);
166  }
167 
172  function getBccs() {
173  return $this->getData('bccs');
174  }
175 
180  function setBccs($bccs) {
181  $this->setData('bccs', $bccs);
182  }
183 
189  function promoteCcsIfNoRecipients() {
190  $ccs = $this->getCcs();
191  $recipients = $this->getRecipients();
192  if (empty($recipients)) {
193  $this->setRecipients($ccs);
194  $this->setCcs(array());
195  return true;
196  }
197  return false;
198  }
199 
203  function clearAllRecipients() {
204  $this->setRecipients(array());
205  $this->setCcs(array());
206  $this->setBccs(array());
207  }
208 
214  function addHeader($name, $content) {
215  $updated = false;
216 
217  if (($headers = $this->getData('headers')) == null) {
218  $headers = array();
219  }
220 
221  foreach ($headers as $key => $value) {
222  if ($value['name'] == $name) {
223  $headers[$key]['content'] = $content;
224  $updated = true;
225  }
226  }
227 
228  if (!$updated) {
229  array_push($headers, array('name' => $name,'content' => $content));
230  }
231 
232  $this->setData('headers', $headers);
233  }
234 
239  function getHeaders() {
240  return $this->getData('headers');
241  }
242 
247  function setHeaders(&$headers) {
248  $this->setData('headers', $headers);
249  }
250 
258  function addAttachment($filePath, $fileName = '', $contentType = '', $contentDisposition = 'attachment') {
259  if ($attachments =& $this->getData('attachments') == null) {
260  $attachments = array();
261  }
262 
263  /* If the arguments $fileName and $contentType are not specified,
264  then try and determine them automatically. */
265  if (empty($fileName)) {
266  $fileName = basename($filePath);
267  }
268 
269  if (empty($contentType)) {
270  $contentType = PKPString::mime_content_type($filePath);
271  if (empty($contentType)) $contentType = 'application/x-unknown-content-type';
272  }
273 
274  array_push($attachments, array(
275  'path' => $filePath,
276  'filename' => $fileName,
277  'content-type' => $contentType
278  ));
279 
280  $this->setData('attachments', $attachments);
281  }
282 
287  function &getAttachments() {
288  $attachments =& $this->getData('attachments');
289  return $attachments;
290  }
291 
296  function hasAttachments() {
297  $attachments =& $this->getAttachments();
298  return ($attachments != null && count($attachments) != 0);
299  }
300 
306  function setFrom($email, $name = '') {
307  $this->setData('from', array('name' => $name, 'email' => $email));
308  }
309 
314  function getFrom() {
315  return $this->getData('from');
316  }
317 
323  function setReplyTo($email, $name = '') {
324  if ($email === null) $this->setData('replyTo', null);
325  $this->setData('replyTo', array(array('name' => $name, 'email' => $email)));
326  }
327 
333  function addReplyTo($email, $name = '') {
334  if (($replyTos = $this->getData('replyTo')) == null) {
335  $replyTos = array();
336  }
337  array_push($replyTos, array('name' => $name, 'email' => $email));
338 
339  $this->setData('replyTo', $replyTo);
340  }
341 
342 
347  function getReplyTo() {
348  return $this->getData('replyTo');
349  }
350 
355  function getReplyToString($send = false) {
356  return $this->getAddressArrayString($this->getReplyTo(), true, $send);
357  }
358 
363  function setSubject($subject) {
364  $this->setData('subject', $subject);
365  }
366 
371  function getSubject() {
372  return $this->getData('subject');
373  }
374 
379  function setBody($body) {
380  $this->setData('body', $body);
381  }
382 
387  function getBody() {
388  return $this->getData('body');
389  }
390 
396  function getFromString($send = false) {
397  $from = $this->getFrom();
398  if ($from == null) {
399  return null;
400  }
401  return (self::encodeDisplayName($from['name'], $send) . ' <'.$from['email'].'>');
402  }
403 
409  function getAddressArrayString($addresses, $includeNames = true, $send = false) {
410  if ($addresses == null) {
411  return null;
412 
413  } else {
414  $addressString = '';
415 
416  foreach ($addresses as $address) {
417  if (!empty($addressString)) {
418  $addressString .= ', ';
419  }
420 
421  if (empty($address['name']) || !$includeNames) {
422  $addressString .= $address['email'];
423 
424  } else {
425  $addressString .= self::encodeDisplayName($address['name'], $send) . ' <'.$address['email'].'>';
426  }
427  }
428 
429  return $addressString;
430  }
431  }
432 
437  function getRecipientString() {
438  return $this->getAddressArrayString($this->getRecipients());
439  }
440 
445  function getCcString() {
446  return $this->getAddressArrayString($this->getCcs());
447  }
448 
453  function getBccString() {
454  return $this->getAddressArrayString($this->getBccs(), false);
455  }
456 
457 
462  function send() {
463  if (HookRegistry::call('Mail::send', array($this))) return true;
464 
465  // Replace all the private parameters for this message.
466  $mailBody = $this->getBody();
467  if (is_array($this->privateParams)) {
468  foreach ($this->privateParams as $name => $value) {
469  $mailBody = str_replace($name, $value, $mailBody);
470  }
471  }
472 
473  $mailer = new \PHPMailer\PHPMailer\PHPMailer();
474  $mailer->IsHTML(true);
475  $mailer->Encoding = 'base64';
476  if (Config::getVar('email', 'smtp')) {
477  $mailer->IsSMTP();
478  $mailer->Port = Config::getVar('email', 'smtp_port');
479  if (($s = Config::getVar('email', 'smtp_auth')) != '') {
480  $mailer->SMTPSecure = $s;
481  $mailer->SMTPAuth = true;
482  }
483  $mailer->Host = Config::getVar('email', 'smtp_server');
484  $mailer->Username = Config::getVar('email', 'smtp_username');
485  $mailer->Password = Config::getVar('email', 'smtp_password');
486  if (Config::getVar('debug', 'show_stacktrace')) {
487  // debug level 3 represents client and server interaction, plus initial connection debugging
488  $mailer->SMTPDebug = 3;
489  $mailer->Debugoutput = 'error_log';
490  }
491  if (Config::getVar('email', 'smtp_suppress_cert_check')) {
492  // disabling the SMTP certificate check.
493  $mailer->SMTPOptions = array(
494  'ssl' => array(
495  'verify_peer' => false,
496  'verify_peer_name' => false,
497  'allow_self_signed' => true
498  )
499  );
500  }
501  }
502  $mailer->CharSet = Config::getVar('i18n', 'client_charset');
503  if (($t = $this->getContentType()) != null) $mailer->ContentType = $t;
504  $mailer->XMailer = 'Public Knowledge Project Suite v3';
505  $mailer->WordWrap = MAIL_WRAP;
506  foreach ((array) $this->getHeaders() as $header) {
507  $mailer->AddCustomHeader($header['key'], $mailer->SecureHeader($header['content']));
508  }
509  $request = Application::get()->getRequest();
510  if (($f = $this->getFrom()) != null) {
511  if (Config::getVar('email', 'force_default_envelope_sender') && Config::getVar('email', 'default_envelope_sender') && Config::getVar('email', 'force_dmarc_compliant_from')) {
512  /* If a DMARC compliant RFC5322.From was requested we need to promote the original RFC5322.From into a Reply-to header
513  * and then munge the RFC5322.From */
514  $alreadyExists = false;
515  foreach ((array) $this->getReplyTo() as $r) {
516  if ($r['email'] === $f['email']) {
517  $alreadyExists = true;
518  }
519  }
520  if (!$alreadyExists) {
521  $mailer->AddReplyTo($f['email'], $f['name']);
522  }
523 
524  $site = $request->getSite();
525 
526  // Munge the RFC5322.From
527  if (Config::getVar('email', 'dmarc_compliant_from_displayname')) {
528  $patterns = array('#%n#', '#%s#');
529  $replacements = array($f['name'], $site->getLocalizedTitle());
530  $f['name'] = preg_replace($patterns, $replacements, Config::getVar('email', 'dmarc_compliant_from_displayname'));
531  } else {
532  $f['name'] = '';
533  }
534  $f['email'] = Config::getVar('email', 'default_envelope_sender');
535  }
536  // this sets both the envelope sender (RFC5321.MailFrom) and the From: header (RFC5322.From)
537  $mailer->SetFrom($f['email'], $f['name']);
538  }
539  // Set the envelope sender (RFC5321.MailFrom)
540  if (($s = $this->getEnvelopeSender()) != null) $mailer->Sender = $s;
541  foreach ((array) $this->getReplyTo() as $r) {
542  $mailer->AddReplyTo($r['email'], $r['name']);
543  }
544  foreach ((array) $this->getRecipients() as $recipientInfo) {
545  $mailer->AddAddress($recipientInfo['email'], $recipientInfo['name']);
546  }
547  foreach ((array) $this->getCcs() as $ccInfo) {
548  $mailer->AddCC($ccInfo['email'], $ccInfo['name']);
549  }
550  foreach ((array) $this->getBccs() as $bccInfo) {
551  $mailer->AddBCC($bccInfo['email'], $bccInfo['name']);
552  }
553  $mailer->Subject = $this->getSubject();
554  $mailer->Body = $mailBody;
555  $mailer->AltBody = PKPString::html2text($mailBody);
556 
557  $remoteAddr = $mailer->SecureHeader($request->getRemoteAddr());
558  if ($remoteAddr != '') $mailer->AddCustomHeader("X-Originating-IP: $remoteAddr");
559 
560  foreach ((array) $this->getAttachments() as $attachmentInfo) {
561  $mailer->AddAttachment(
562  $attachmentInfo['path'],
563  $attachmentInfo['filename'],
564  'base64',
565  $attachmentInfo['content-type']
566  );
567  }
568 
569  try {
570  $success = $mailer->Send();
571  if (!$success) {
572  error_log($mailer->ErrorInfo);
573  return false;
574  }
575  } catch (phpmailerException $e) {
576  error_log($mailer->ErrorInfo);
577  return false;
578  }
579  return true;
580  }
581 
588  static function encodeDisplayName($displayName, $send = false) {
589  if (PKPString::regexp_match('!^[-A-Za-z0-9\!#\$%&\'\*\+\/=\?\^_\`\{\|\}~]+$!', $displayName)) return $displayName;
590  return ('"' . ($send ? PKPString::encode_mime_header(str_replace(
591  array('"', '\\'),
592  '',
593  $displayName
594  )) : str_replace(
595  array('"', '\\'),
596  '',
597  $displayName
598  )) . '"');
599  }
600 }
601 
602 
DataObject\getData
& getData($key, $locale=null)
Definition: DataObject.inc.php:100
Mail\hasAttachments
hasAttachments()
Definition: Mail.inc.php:299
Mail\getHeaders
getHeaders()
Definition: Mail.inc.php:242
Mail\__construct
__construct()
Definition: Mail.inc.php:33
Mail\getBccs
getBccs()
Definition: Mail.inc.php:175
DataObject
Any class with an associated DAO should extend this class.
Definition: DataObject.inc.php:18
Mail\setHeaders
setHeaders(&$headers)
Definition: Mail.inc.php:250
Mail\clearAllRecipients
clearAllRecipients()
Definition: Mail.inc.php:206
Mail\setSubject
setSubject($subject)
Definition: Mail.inc.php:366
Mail\getFrom
getFrom()
Definition: Mail.inc.php:317
Mail\getSubject
getSubject()
Definition: Mail.inc.php:374
Mail\getCcs
getCcs()
Definition: Mail.inc.php:145
Mail\addBcc
addBcc($email, $name='')
Definition: Mail.inc.php:162
Mail\addCc
addCc($email, $name='')
Definition: Mail.inc.php:132
Mail\getAddressArrayString
getAddressArrayString($addresses, $includeNames=true, $send=false)
Definition: Mail.inc.php:412
Mail\getReplyTo
getReplyTo()
Definition: Mail.inc.php:350
Mail\addAttachment
addAttachment($filePath, $fileName='', $contentType='', $contentDisposition='attachment')
Definition: Mail.inc.php:261
Mail\setPrivateParams
setPrivateParams($privateParams)
Definition: Mail.inc.php:54
Mail\addPrivateParam
addPrivateParam($name, $value)
Definition: Mail.inc.php:46
Mail\setBody
setBody($body)
Definition: Mail.inc.php:382
Mail\send
send()
Definition: Mail.inc.php:465
Mail\getBccString
getBccString()
Definition: Mail.inc.php:456
Mail\getRecipientString
getRecipientString()
Definition: Mail.inc.php:440
PKPString\html2text
static html2text($html)
Definition: PKPString.inc.php:395
Mail
Class defining basic operations for handling and sending emails.
Definition: Mail.inc.php:23
Mail\promoteCcsIfNoRecipients
promoteCcsIfNoRecipients()
Definition: Mail.inc.php:192
Mail\encodeDisplayName
static encodeDisplayName($displayName, $send=false)
Definition: Mail.inc.php:591
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
Mail\getEnvelopeSender
getEnvelopeSender()
Definition: Mail.inc.php:86
PKPString\mime_content_type
static mime_content_type($filename, $suggestedExtension='')
Definition: PKPString.inc.php:312
Mail\getRecipients
getRecipients()
Definition: Mail.inc.php:115
Mail\setRecipients
setRecipients($recipients)
Definition: Mail.inc.php:123
Mail\getAttachments
& getAttachments()
Definition: Mail.inc.php:290
Mail\addRecipient
addRecipient($email, $name='')
Definition: Mail.inc.php:63
Mail\addReplyTo
addReplyTo($email, $name='')
Definition: Mail.inc.php:336
Mail\getFromString
getFromString($send=false)
Definition: Mail.inc.php:399
Mail\setCcs
setCcs($ccs)
Definition: Mail.inc.php:153
Mail\setContentType
setContentType($contentType)
Definition: Mail.inc.php:107
Mail\getReplyToString
getReplyToString($send=false)
Definition: Mail.inc.php:358
PKPString\encode_mime_header
static encode_mime_header($string)
Definition: PKPString.inc.php:206
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
PKPString\regexp_match
static regexp_match($pattern, $subject)
Definition: PKPString.inc.php:245
Mail\setEnvelopeSender
setEnvelopeSender($envelopeSender)
Definition: Mail.inc.php:77
Mail\getContentType
getContentType()
Definition: Mail.inc.php:99
Mail\setBccs
setBccs($bccs)
Definition: Mail.inc.php:183
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
Mail\addHeader
addHeader($name, $content)
Definition: Mail.inc.php:217
Mail\getBody
getBody()
Definition: Mail.inc.php:390
DataObject\setData
setData($key, $value, $locale=null)
Definition: DataObject.inc.php:132
Mail\getCcString
getCcString()
Definition: Mail.inc.php:448
Mail\setFrom
setFrom($email, $name='')
Definition: Mail.inc.php:309
Mail\$privateParams
$privateParams
Definition: Mail.inc.php:28
Mail\setReplyTo
setReplyTo($email, $name='')
Definition: Mail.inc.php:326