3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
6 * Generic email for Galette
10 * Copyright © 2009-2023 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2009-2023 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.7dev - 2009-12-10
37 namespace Galette\Core
;
41 use PHPMailer\PHPMailer\PHPMailer
;
44 * Generic email for Galette
49 * @author Johan Cwiklinski <johan@x-tnd.be>
50 * @copyright 2009-2023 The Galette Team
51 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
52 * @link http://galette.tuxfamily.org
53 * @since Available since 0.7dev - 2009-03-07
57 public const MAIL_ERROR
= 0;
58 public const MAIL_SENT
= 1;
60 public const METHOD_DISABLED
= 0;
61 public const METHOD_PHPMAIL
= 1;
62 public const METHOD_SMTP
= 2;
63 public const METHOD_QMAIL
= 3;
64 public const METHOD_GMAIL
= 4;
65 public const METHOD_SENDMAIL
= 5;
67 public const SENDER_PREFS
= 0;
68 public const SENDER_CURRENT
= 1;
69 public const SENDER_OTHER
= 2;
72 private $sender_address;
76 private $word_wrap = 70;
77 private $timeout = 300;
79 private $errors = array();
80 private $recipients = array();
83 protected $attachments = array();
90 * @param Preferences $preferences Preferences instance
92 public function __construct(Preferences
$preferences)
94 $this->preferences
= $preferences;
96 $preferences->pref_email_nom
,
97 $preferences->pref_email
102 * Initialize PHPMailer
106 private function initMailer()
110 $this->mail
= new PHPMailer();
111 $this->mail
->Timeout
= $this->timeout
;
113 switch ($this->preferences
->pref_mail_method
) {
114 case self
::METHOD_SMTP
:
115 case self
::METHOD_GMAIL
:
116 //if we want to send emails using a smtp server
117 $this->mail
->IsSMTP();
118 // enables SMTP debug information
119 if (Galette
::isDebugEnabled()) {
120 $this->mail
->SMTPDebug
= 4;
121 //cannot use a callable here; this prevents class to be serialized
122 //see https://bugs.galette.eu/issues/1468
123 $this->mail
->Debugoutput
= 'error_log';
126 if ($this->preferences
->pref_mail_method
== self
::METHOD_GMAIL
) {
127 // sets GMAIL as the SMTP server
128 $this->mail
->Host
= "smtp.gmail.com";
129 // enable SMTP authentication
130 $this->mail
->SMTPAuth
= true;
131 // sets the prefix to the servier
132 $this->mail
->SMTPSecure
= "tls";
133 // set the SMTP port for the GMAIL server
134 $this->mail
->Port
= 587;
136 $this->mail
->Host
= $this->preferences
->pref_mail_smtp_host
;
137 $this->mail
->SMTPAuth
= $this->preferences
->pref_mail_smtp_auth
;
139 if (!$this->preferences
->pref_mail_smtp_secure ||
$this->preferences
->pref_mail_allow_unsecure
) {
140 //Allow "unsecure" SMTP connections if user has asked fot it or
141 //if user did not request TLS explicitely
142 $this->mail
->SMTPOptions
= array(
144 'verify_peer' => false,
145 'verify_peer_name' => false,
146 'allow_self_signed' => true
152 $this->preferences
->pref_mail_smtp_port
153 && $this->preferences
->pref_mail_smtp_port
!= ''
155 // set the SMTP port for the SMTP server
156 $this->mail
->Port
= $this->preferences
->pref_mail_smtp_port
;
159 '[' . get_class($this) .
160 ']No SMTP port provided. Switch to default (25).',
163 $this->mail
->Port
= $this->preferences
->pref_mail_smtp_secure ?
587 : 25;
166 if ($this->preferences
->pref_mail_smtp_secure
&& $this->mail
->Port
== 465) {
167 $this->mail
->SMTPSecure
= "ssl";
168 } elseif ($this->preferences
->pref_mail_smtp_secure
&& $this->mail
->Port
== 587) {
169 $this->mail
->SMTPSecure
= "tls";
173 // SMTP account username
174 $this->mail
->Username
= $this->preferences
->pref_mail_smtp_user
;
175 // SMTP account password
176 $this->mail
->Password
= $this->preferences
->pref_mail_smtp_password
;
178 case self
::METHOD_SENDMAIL
:
179 // telling the class to use Sendmail transport
180 $this->mail
->IsSendmail();
182 case self
::METHOD_QMAIL
:
183 // telling the class to use QMail transport
184 $this->mail
->IsQmail();
188 $this->mail
->CharSet
= 'UTF-8';
189 $this->mail
->SetLanguage($i18n->getAbbrev());
191 if ($this->preferences
->pref_bool_wrap_mails
) {
192 $this->mail
->WordWrap
= $this->word_wrap
;
194 $this->word_wrap
= 0;
199 * Sets the recipients
200 * For mailing convenience, all recipients will be added as BCC,
201 * regular recipient will be the sender.
203 * @param array $recipients Array (mail=>name) of all recipients
207 public function setRecipients($recipients)
211 if ($this->mail
=== null) {
215 if (!empty($recipients)) {
216 $this->recipients
= array();
217 foreach ($recipients as $mail => $name) {
218 if (self
::isValidEmail($mail)) {
219 $this->recipients
[$mail] = $name;
220 $this->mail
->AddBCC($mail, $name);
222 //one of addresses is not valid :
223 //- set $res to false
228 '[' . get_class($this) .
229 '] One of recipients address is not valid.',
232 $this->mail
->ClearBCCs();
237 $this->mail
->ClearBCCs();
244 * Apply final header to email and send it :-)
246 * @return integer Either GaletteMail::MAIL_ERROR|GaletteMail::MAIL_SENT
248 public function send()
250 if ($this->mail
=== null) {
255 $this->mail
->SetFrom(
256 $this->getSenderAddress(),
257 $this->getSenderName()
259 // Add a Reply-To field in the email headers.
261 if ($this->preferences
->pref_email_reply_to
) {
262 $this->mail
->AddReplyTo($this->preferences
->pref_email_reply_to
);
264 $this->mail
->AddReplyTo($this->getSenderAddress());
269 //the email is html :(
270 $this->mail
->AltBody
= $this->cleanedHtml();
271 $this->mail
->IsHTML(true);
273 //the email is plaintext :)
274 $this->mail
->AltBody
= '';
275 $this->mail
->IsHTML(false);
278 $this->mail
->Subject
= $this->subject
;
279 $this->mail
->Body
= $this->message
;
281 //set at least on real recipient (not bcc)
282 if (count($this->recipients
) === 1) {
283 //there is only one recipient, clean bcc and readd as simple recipient
284 $this->mail
->ClearBCCs();
285 $this->mail
->AddAddress(
286 key($this->recipients
),
287 current($this->recipients
)
290 //we're sending a mailing. Set main recipient to sender
291 $this->mail
->AddAddress(
292 $this->getSenderAddress(),
293 $this->getSenderName()
297 $signature = $this->preferences
->getMailSignature($this->mail
);
298 if ($signature != '') {
300 //we are sending html message
301 //apply email sign to text version
302 $this->mail
->AltBody
.= $signature;
303 //then apply email sign to html version
304 $sign_style = 'color:grey;border-top:1px solid #ccc;margin-top:2em';
305 $hsign = '<div style="' . $sign_style . '">' .
306 nl2br($signature) . '</div>';
307 $this->mail
->Body
.= $hsign;
309 $this->mail
->Body
.= $signature;
314 if (count($this->attachments
) > 0) {
315 foreach ($this->attachments
as $attachment) {
316 $this->mail
->AddAttachment(
317 $attachment->getDestDir() . $attachment->getFileName()
323 //reinit errors array
324 $this->errors
= array();
325 //let's send the email
326 if (!$this->mail
->Send()) {
327 $this->errors
[] = $this->mail
->ErrorInfo
;
329 'An error occurred sending email to: ' .
330 implode(', ', array_keys($this->recipients
)) .
331 "\n" . $this->mail
->ErrorInfo
,
335 return self
::MAIL_ERROR
;
338 foreach ($this->recipients
as $k => $v) {
339 $txt .= $v . ' (' . $k . '), ';
342 'An email has been sent to: ' . $txt,
346 return self
::MAIL_SENT
;
348 } catch (Throwable
$e) {
350 'Error sending message: ' . $e->getMessage(),
353 $this->errors
[] = $e->getMessage();
355 return self
::MAIL_ERROR
;
360 * Check if an email address is valid
362 * @param string $address the email address to check
366 public static function isValidEmail($address)
368 $valid = PHPMailer
::ValidateAddress($address);
371 '[GaletteMail] Address `' . $address . '` is not valid ',
379 * Check if a string is an url
381 * @param string $url the url to check
385 public static function isUrl($url)
388 '|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i',
393 '[GaletteMail] `' . $url . '` is not an url',
401 * Clean a string embedding html, producing AltText for html emails
403 * @return string current message in plaintext format
405 protected function cleanedHtml()
407 $html = $this->message
;
408 $txt = \Soundasleep\Html2Text
::convert($html);
413 * Retrieve PHPMailer main object
415 * @return PHPMailer object
417 protected function getPhpMailer()
423 * Is the email HTML formatted?
425 * @param boolean $set The value to set
429 public function isHTML($set = null)
442 public function getSenderName()
444 return $this->sender_name
;
452 public function getSenderAddress()
454 return $this->sender_address
;
460 * @return string The subject
462 public function getSubject()
464 return $this->subject
;
468 * Retrieve array of errors
472 public function getErrors()
474 return $this->errors
;
480 * @return string The message
482 public function getMessage()
484 return $this->message
;
488 * Get the message, wrapped
490 * @return string Wrapped message
492 public function getWrappedMessage()
494 if ($this->word_wrap
> 0) {
495 if ($this->mail
=== null) {
499 return $this->mail
->wrapText(
504 return $this->message
;
511 * @param string $subject The subject
513 * @return GaletteMail
515 public function setSubject($subject)
517 $this->subject
= $subject;
524 * @param string $message The message
526 * @return GaletteMail
528 public function setMessage($message)
530 $this->message
= $message;
537 * @param string $name Sender name
538 * @param string $address Sender address
540 * @return GaletteMail
542 public function setSender($name, $address)
544 $this->sender_name
= $name;
545 $this->sender_address
= $address;
550 * Set timeout on SMTP connexion
552 * @param integer $timeout SMTP timeout
554 * @return GaletteMail
556 public function setTimeout($timeout)
558 $this->timeout
= $timeout;