Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.Message.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 
7 namespace Dcp\Mail;
8 /**
9  * Compose a mail with body and attachments and send it using the SMTP
10  * server referenced by Dynacase's parameters.
11  *
12  * The (MIME) structure of the mail is:
13  *
14  * MIME[multipart/mixed]
15  * |-(1)-> MIME[multipart/related]
16  * | |-(1.1)-> A 'text/html' or 'text/plain' body (::setBody())
17  * | '-(1.2)-> Images related to body (::addBodyRelatedAttachment())
18  * '-(2)-> n x attachments (::addAttachment())
19  *
20  * Sample usage:
21  *
22  * --8<--
23  * $message = new \Dcp\Mail\Message();
24  *
25  * $message->setFrom(new \Dcp\Mail\Address('john.steed@example.net', 'John Steed (The Avengers)'));
26  * $message->addTo(new \Dcp\Mail\Address('emma.peel@example.net', 'Emma Peel (The Avengers)'));
27  * $message->addCc(new \Dcp\Mail\Address('mother@eexample.net', 'Mother'));
28  *
29  * $message->setSubject('Our next mission');
30  *
31  * $message->setBody(new \Dcp\Mail\Body('<html>A picture is worth a thousand words: <img src="cid:img01" /></html>', 'text/html'));
32  * $message->addBodyRelatedAttachment(new \Dcp\Mail\RelatedAttachment('/tmp/next-mission.png', 'next-mission.png', 'image/png', 'img01'));
33  *
34  * $message->addAttachment(new \Dcp\Mail\Attachment('/tmp/plan.pdf', 'The plan.pdf', 'application/pdf'));
35  *
36  * $err = $message->send();
37  * if ($err != '') {
38  * throw new \Exception(sprintf("Error sending message: %s", $err));
39  * }
40  * -->8--
41  *
42  * @package Dcp\Mail
43  */
44 class Message
45 {
46  const className = __CLASS__;
47  /**
48  * @var Address
49  */
50  public $from = null;
51  /**
52  * SMTP transport sender address ('MAIL FROM:')
53  *
54  * @var Address
55  */
56  public $sender = null;
57  /**
58  * @var Address[]
59  */
60  public $to = array();
61  /**
62  * @var Address[]
63  */
64  public $cc = array();
65  /**
66  * @var Address[]
67  */
68  public $bcc = array();
69  public $subject = '';
70  /**
71  * @var Body
72  */
73  public $body = null;
74  /**
75  * @var RelatedAttachment[]
76  */
77  public $bodyRelated = array();
78  /**
79  * @var Body
80  */
81  public $altBody = null;
82  /**
83  * @var Attachment[]
84  */
85  public $attachments = array();
86  /**
87  * Parse a string containing mail addresses and return
88  * list of\Dcp\Mail\Address objects
89  * @param $str
90  * @return \Dcp\Mail\Address[]
91  */
92  private function stringToAddress($str)
93  {
94  $addresses = array();
95  $parser = new MailAddrParser();
96  try {
97  $addresses = $parser->parse($str);
98  }
99  catch(MailAddrParserException $e) {
100  }
101  return $addresses;
102  }
103  private function isAddress($obj)
104  {
105  return is_a($obj, Address::className);
106  }
107  /**
108  * Set 'From:' address used by the mail's body 'From:' field and the SMTP protocol.
109  *
110  * @param Address|string $address
111  */
112  public function setFrom($address)
113  {
114  if ($this->isAddress($address)) {
115  $this->from = $address;
116  } elseif (is_scalar($address)) {
117  $addr = $this->stringToAddress($address);
118  if (count($addr) > 0) {
119  $this->from = $addr[0];
120  }
121  }
122  }
123  /**
124  * Set SMTP sender transport address ('MAIL FROM:')
125  *
126  * @param Address|string $address
127  */
128  public function setSender($address)
129  {
130  if ($this->isAddress($address)) {
131  $this->sender = $address;
132  } elseif (is_scalar($address)) {
133  $addr = $this->stringToAddress($address);
134  if (count($addr) > 0) {
135  $this->sender = $addr[0];
136  }
137  }
138  }
139 
140  /**
141  * Get To email addresses
142  * @return string
143  */
144  public function getTo() {
145  return $this->addressesToString($this->to);
146  }
147 
148  /**
149  * Get Cc email addresses
150  * @return string
151  */
152  public function getCC() {
153  return $this->addressesToString($this->cc);
154  }
155  /**
156  * Get Bcc email addresses
157  * @return string
158  */
159  public function getBCC() {
160  return $this->addressesToString($this->bcc);
161  }
162  /**
163  * Get From email address
164  * @return string
165  */
166  public function getFrom() {
167  return $this->addressesToString([$this->from]);
168  }
169  /**
170  * @param Address[] $tAddresses
171  *
172  * @return string
173  */
174  protected function addressesToString(array $tAddresses) {
175  $tos=[];
176  foreach ($tAddresses as $to) {
177  if (is_a($to, 'Dcp\\Mail\\Address') && $to->address) {
178  if ($to->name) {
179  $tos[] = sprintf('"%s" <%s>', str_replace('"', ' ', $to->name), $to->address);
180  } else {
181  $tos[] =$to->address;
182  }
183  }
184  }
185  return implode(",", $tos);
186  }
187 
188  /**
189  * Add 'To:' recipients.
190  *
191  * @param Address|string $address
192  */
193  public function addTo($address)
194  {
195  if ($this->isAddress($address)) {
196  $this->to[] = $address;
197  } elseif (is_scalar($address)) {
198  foreach ($this->stringToAddress($address) as $addr) {
199  $this->to[] = $addr;
200  }
201  }
202  }
203  /**
204  * Reset list of 'To:' recipients
205  */
206  public function resetTo()
207  {
208  $this->to = array();
209  }
210  /**
211  * Add 'Cc:' recipients.
212  *
213  * @param Address|string $address
214  */
215  public function addCc($address)
216  {
217  if ($this->isAddress($address)) {
218  $this->cc[] = $address;
219  } elseif (is_scalar($address)) {
220  foreach ($this->stringToAddress($address) as $addr) {
221  $this->cc[] = $addr;
222  }
223  }
224  }
225  /**
226  * Reset list of 'Cc:' recipients.
227  */
228  public function resetCc()
229  {
230  $this->cc = array();
231  }
232  /**
233  * Add 'Bcc:' recipients.
234  *
235  * @param Address|string $address
236  */
237  public function addBcc($address)
238  {
239  if ($this->isAddress($address)) {
240  $this->bcc[] = $address;
241  } elseif (is_scalar($address)) {
242  foreach ($this->stringToAddress($address) as $addr) {
243  $this->bcc[] = $addr;
244  }
245  }
246  }
247  /**
248  * Reset list of 'Bcc:' recipients.
249  */
250  public function resetBcc()
251  {
252  $this->bcc = array();
253  }
254  /**
255  * Set mail's 'Subject:' field.
256  *
257  * @param $subject
258  */
259  public function setSubject($subject)
260  {
261  $this->subject = $subject;
262  }
263  /**
264  * Set main mail's body.
265  *
266  * @param Body $body
267  */
268  public function setBody(Body & $body)
269  {
270  $this->body = $body;
271  }
272  /**
273  * Add an attachment related to the body (with the use of cid:xxx URLs).
274  *
275  * @param RelatedAttachment $attachment
276  */
277  public function addBodyRelatedAttachment(RelatedAttachment & $attachment)
278  {
279  $this->bodyRelated[] = $attachment;
280  }
281  /**
282  * Reset list of body's related attachments.
283  */
284  public function resetBodyRelatedAttachment()
285  {
286  $this->bodyRelated = array();
287  }
288  /**
289  * Set alternate body (e.g. plain text view of a main HTML body).
290  *
291  * @param Body $body
292  */
293  public function setAltBody(Body & $body)
294  {
295  $this->altBody = $body;
296  }
297  /**
298  * Add attachments.
299  *
300  * @param Attachment $attachment
301  */
302  public function addAttachment(Attachment & $attachment)
303  {
304  $this->attachments[] = $attachment;
305  }
306  /**
307  * Reset list of attachments.
308  */
309  public function resetAttachment()
310  {
311  $this->attachments = array();
312  }
313  /**
314  * Send the message
315  *
316  * @return string error message on failure or empty string if successful
317  */
318  public function send()
319  {
320  return $this->_sendWithPHPMailer();
321  }
322  private function _sendWithPHPMailer()
323  {
324  include_once ("WHAT/Lib.Common.php");
325  $lcConfig = getLocaleConfig();
326  $mail = new \PHPMailer();
327  /*
328  * SMTPAutoTLS was introduced in v5.2.10 and is set to bool(true) by
329  * default.
330  *
331  * We set it back to bool(false) for compatibility and prevent errors
332  * with existing SMTP servers that could advertise TLS with non-valid
333  * certificates.
334  *
335  * If a client wants to use TLS, it can explicitly specify it with a
336  * "tls://<hostname>" URI in the SMTP_HOST parameter.
337  */
338  $mail->SMTPAutoTLS = false;
339  /*
340  * Timeout was changed in v5.2.10 to 300 seconds to conform with RFC2821.
341  *
342  * We set it back to 10 to keep previous behaviour.
343  */
344  $mail->Timeout = 10;
345  $mail->setLanguage($lcConfig['locale']);
346  $mail->isSMTP();
347  $host = getParam('SMTP_HOST', 'localhost');
348  $port = getParam('SMTP_PORT', 25);
349  $mail->Host = $host;
350  $mail->Port = $port;
351  $login = getParam('SMTP_LOGIN');
352  if ($login) {
353  $mail->SMTPAuth = true;
354  $password = getParam('SMTP_PASSWORD');
355  $mail->Username = $login;
356  $mail->Password = $password;
357  }
358  if (!isset($this->sender)) {
359  $sender = getParam('SMTP_SENDER', '');
360  if ($sender !== '') {
361  $parsedMail = $this->stringToAddress($sender);
362  if (count($parsedMail) > 0) {
363  $sender = $parsedMail[0];
364  if (isset($this->from)) {
365  /* Copy original "From:" into "Sender:" */
366  $mail->addCustomHeader('Sender', $this->from->address);
367  /* Set "Reply-To:" with original "From:" address */
368  $mail->addReplyTo($this->from->address, $this->from->name);
369  }
370  /* Set envelope sender */
371  $this->setSender($sender->address);
372  if ($sender->name === '') {
373  /*
374  * Overwrite original "From:" with envelope sender address while keeping original display name
375  */
376  $this->setFrom(new Address($sender->address, $this->from->name));
377  } else {
378  /*
379  * Overwrite original "From:" with envelope sender address while keeping original display name
380  * and showing sender's display name in "via" suffix
381  */
382  $this->setFrom(new Address($sender->address, sprintf("%s via %s", $this->from->name, $sender->name)));
383  }
384  }
385  }
386  }
387  if (isset($this->sender)) {
388  /* Set envelope sender address */
389  $mail->Sender = $this->sender->address;
390  }
391  if (isset($this->from)) {
392  $mail->From = $this->from->address;
393  $mail->FromName = $this->from->name;
394  }
395  foreach ($this->to as $to) {
396  $mail->addAddress($to->address, $to->name);
397  }
398  foreach ($this->cc as $to) {
399  $mail->addCC($to->address, $to->name);
400  }
401  foreach ($this->bcc as $to) {
402  $mail->addBCC($to->address, $to->name);
403  }
404  $mail->CharSet = "UTF-8";
405  $mail->XMailer = sprintf("Dynacase Platform %s", \ApplicationParameterManager::getParameterValue('CORE', 'VERSION'));
406  $mail->MessageID = '<' . strftime("%Y%M%d%H%M%S-", time()) . rand(1, 65535) . "@%s>";
407  $mail->MessageID = sprintf('<%s%s@%s>', strftime("%Y%M%d%H%M%S-", time()) , rand(1, 65535) , $host);
408  $mail->Subject = $this->subject;
409  $mail->AllowEmpty = true;
410  if (isset($this->body)) {
411  if ($this->body->type == 'text/html') {
412  $mail->isHTML(true);
413  }
414  $mail->Body = $this->body->data;
415  }
416  foreach ($this->bodyRelated as $attachment) {
417  $mail->addEmbeddedImage($attachment->file, $attachment->cid, $attachment->name, 'base64', $attachment->type);
418  }
419  if (isset($this->altBody)) {
420  $mail->AltBody = $this->altBody->data;
421  }
422  foreach ($this->attachments as $attachment) {
423  $mail->addAttachment($attachment->file, $attachment->name, 'base64', $attachment->type);
424  }
425  $ret = $mail->send();
426  if ($ret === false) {
427  return $mail->ErrorInfo;
428  }
429  return '';
430  }
431 }
setSubject($subject)
$ret
static getParameterValue($application, $parameterName)
addressesToString(array $tAddresses)
getLocaleConfig($core_lang= '')
Definition: Lib.Common.php:853
setBody(Body &$body)
addBodyRelatedAttachment(RelatedAttachment &$attachment)
setAltBody(Body &$body)
getParam($name, $def="")
must be in core or global type
Definition: Lib.Common.php:193
$login
Definition: dav.php:40
addAttachment(Attachment &$attachment)
← centre documentaire © anakeen