REF Update CiviCRM default PEAR Error handling to be exception rather than just PEAR_...
[civicrm-core.git] / CRM / Admin / Form / Setting / Smtp.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 */
17
18/**
ce064e4f 19 * This class generates form components for Smtp Server.
6a488035
TO
20 */
21class CRM_Admin_Form_Setting_Smtp extends CRM_Admin_Form_Setting {
22 protected $_testButtonName;
8d87a78a 23 protected $_settings = [
24 'allow_mail_from_logged_in_contact' => CRM_Core_BAO_Setting::DIRECTORY_PREFERENCES_NAME,
25 ];
6a488035
TO
26
27 /**
eceb18cc 28 * Build the form object.
6a488035
TO
29 */
30 public function buildQuickForm() {
fc6b10e1 31 $props = [];
042b7393 32 $settings = Civi::settings()->getMandatory('mailing_backend') ?? [];
928f6a96 33 //Load input as readonly whose values are overridden in civicrm.settings.php.
34 foreach ($settings as $setting => $value) {
35 if (isset($value)) {
36 $props[$setting]['readonly'] = TRUE;
37 $setStatus = TRUE;
38 }
39 }
40
fc6b10e1
MW
41 $outBoundOption = [
42 CRM_Mailing_Config::OUTBOUND_OPTION_MAIL => ts('mail()'),
43 CRM_Mailing_Config::OUTBOUND_OPTION_SMTP => ts('SMTP'),
44 CRM_Mailing_Config::OUTBOUND_OPTION_SENDMAIL => ts('Sendmail'),
45 CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED => ts('Disable Outbound Email'),
46 CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB => ts('Redirect to Database'),
47 ];
48 $this->addRadio('outBound_option', ts('Select Mailer'), $outBoundOption, $props['outBound_option'] ?? []);
49
6a488035
TO
50 CRM_Utils_System::setTitle(ts('Settings - Outbound Mail'));
51 $this->add('text', 'sendmail_path', ts('Sendmail Path'));
52 $this->add('text', 'sendmail_args', ts('Sendmail Argument'));
928f6a96 53 $this->add('text', 'smtpServer', ts('SMTP Server'), CRM_Utils_Array::value('smtpServer', $props));
54 $this->add('text', 'smtpPort', ts('SMTP Port'), CRM_Utils_Array::value('smtpPort', $props));
55 $this->addYesNo('smtpAuth', ts('Authentication?'), CRM_Utils_Array::value('smtpAuth', $props));
56 $this->addElement('text', 'smtpUsername', ts('SMTP Username'), CRM_Utils_Array::value('smtpUsername', $props));
57 $this->addElement('password', 'smtpPassword', ts('SMTP Password'), CRM_Utils_Array::value('smtpPassword', $props));
6a488035
TO
58
59 $this->_testButtonName = $this->getButtonName('refresh', 'test');
60
be2fb01f 61 $this->addFormRule(['CRM_Admin_Form_Setting_Smtp', 'formRule']);
6a488035 62 parent::buildQuickForm();
aeb97cc1 63 $buttons = $this->getElement('buttons')->getElements();
98da7d67
AH
64 $buttons[] = $this->createElement(
65 'xbutton',
66 $this->_testButtonName,
67 CRM_Core_Page::crmIcon('fa-envelope-o') . ' ' . ts('Save & Send Test Email'),
68 ['type' => 'submit']
69 );
aeb97cc1 70 $this->getElement('buttons')->setElements($buttons);
928f6a96 71
72 if (!empty($setStatus)) {
73 CRM_Core_Session::setStatus("Some fields are loaded as 'readonly' as they have been set (overridden) in civicrm.settings.php.", '', 'info', array('expires' => 0));
74 }
6a488035
TO
75 }
76
77 /**
eceb18cc 78 * Process the form submission.
177bc889 79 *
80 * @throws \Exception
6a488035
TO
81 */
82 public function postProcess() {
83 // flush caches so we reload details for future requests
84 // CRM-11967
85 CRM_Utils_System::flushCache();
86
87 $formValues = $this->controller->exportValues($this->_name);
88
beac1417
MW
89 Civi::settings()->set('allow_mail_from_logged_in_contact', (!empty($formValues['allow_mail_from_logged_in_contact'])));
90 unset($formValues['allow_mail_from_logged_in_contact']);
91
6a488035
TO
92 $buttonName = $this->controller->getButtonName();
93 // check if test button
94 if ($buttonName == $this->_testButtonName) {
95 if ($formValues['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_DISABLED) {
96 CRM_Core_Session::setStatus(ts('You have selected "Disable Outbound Email". A test email can not be sent.'), ts("Email Disabled"), "error");
0db6c3e1 97 }
481a74f4 98 elseif ($formValues['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB) {
6a488035
TO
99 CRM_Core_Session::setStatus(ts('You have selected "Redirect to Database". A test email can not be sent.'), ts("Email Disabled"), "error");
100 }
101 else {
102 $session = CRM_Core_Session::singleton();
103 $userID = $session->get('userID');
177bc889 104 list($toDisplayName, $toEmail) = CRM_Contact_BAO_Contact::getContactDetails($userID);
6a488035
TO
105
106 //get the default domain email address.CRM-4250
107 list($domainEmailName, $domainEmailAddress) = CRM_Core_BAO_Domain::getNameAndEmail();
108
109 if (!$domainEmailAddress || $domainEmailAddress == 'info@EXAMPLE.ORG') {
f7d2c2ec
FK
110 $fixUrl = CRM_Utils_System::url("civicrm/admin/options/from_email_address", 'action=update&reset=1');
111 CRM_Core_Error::statusBounce(ts('The site administrator needs to enter a valid \'FROM Email Address\' in <a href="%1">Administer CiviCRM &raquo; System Settings &raquo; Option Groups &raquo; From Email Address</a>. The email address used may need to be a valid mail account with your email service provider.', [1 => $fixUrl]));
6a488035 112 }
6a488035
TO
113 if (!$toEmail) {
114 CRM_Core_Error::statusBounce(ts('Cannot send a test email because your user record does not have a valid email address.'));
115 }
116
117 if (!trim($toDisplayName)) {
118 $toDisplayName = $toEmail;
119 }
120
353ffa53
TO
121 $to = '"' . $toDisplayName . '"' . "<$toEmail>";
122 $from = '"' . $domainEmailName . '" <' . $domainEmailAddress . '>';
ba03e3eb 123 $testMailStatusMsg = ts('Sending test email') . ':<br />'
be2fb01f
CW
124 . ts('From: %1', [1 => $domainEmailAddress]) . '<br />'
125 . ts('To: %1', [1 => $toEmail]) . '<br />';
6a488035 126
be2fb01f 127 $params = [];
6a488035
TO
128 if ($formValues['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_SMTP) {
129 $subject = "Test for SMTP settings";
130 $message = "SMTP settings are correct.";
131
132 $params['host'] = $formValues['smtpServer'];
133 $params['port'] = $formValues['smtpPort'];
134
135 if ($formValues['smtpAuth']) {
136 $params['username'] = $formValues['smtpUsername'];
137 $params['password'] = $formValues['smtpPassword'];
353ffa53 138 $params['auth'] = TRUE;
6a488035
TO
139 }
140 else {
141 $params['auth'] = FALSE;
142 }
143
144 // set the localhost value, CRM-3153, CRM-9332
145 $params['localhost'] = $_SERVER['SERVER_NAME'];
146
147 // also set the timeout value, lets set it to 30 seconds
148 // CRM-7510, CRM-9332
149 $params['timeout'] = 30;
150
151 $mailerName = 'smtp';
152 }
153 elseif ($formValues['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_SENDMAIL) {
154 $subject = "Test for Sendmail settings";
155 $message = "Sendmail settings are correct.";
156 $params['sendmail_path'] = $formValues['sendmail_path'];
157 $params['sendmail_args'] = $formValues['sendmail_args'];
158 $mailerName = 'sendmail';
159 }
160 elseif ($formValues['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_MAIL) {
353ffa53
TO
161 $subject = "Test for PHP mail settings";
162 $message = "mail settings are correct.";
6a488035
TO
163 $mailerName = 'mail';
164 }
165
be2fb01f 166 $headers = [
6a488035
TO
167 'From' => $from,
168 'To' => $to,
169 'Subject' => $subject,
be2fb01f 170 ];
6a488035 171
7af71f56 172 $mailer = CRM_Utils_Mail::_createMailer($mailerName, $params);
6a488035 173
6b1506ee 174 try {
6b1506ee
MW
175 $mailer->send($toEmail, $headers, $message);
176 if (defined('CIVICRM_MAIL_LOG') && defined('CIVICRM_MAIL_LOG_AND_SEND')) {
177 $testMailStatusMsg .= '<br />' . ts('You have defined CIVICRM_MAIL_LOG_AND_SEND - mail will be logged.') . '<br /><br />';
178 }
179 if (defined('CIVICRM_MAIL_LOG') && !defined('CIVICRM_MAIL_LOG_AND_SEND')) {
180 CRM_Core_Session::setStatus($testMailStatusMsg . ts('You have defined CIVICRM_MAIL_LOG - no mail will be sent. Your %1 settings have not been tested.', [1 => strtoupper($mailerName)]), ts("Mail not sent"), "warning");
181 }
182 else {
183 CRM_Core_Session::setStatus($testMailStatusMsg . ts('Your %1 settings are correct. A test email has been sent to your email address.', [1 => strtoupper($mailerName)]), ts("Mail Sent"), "success");
184 }
6a488035 185 }
6b1506ee
MW
186 catch (Exception $e) {
187 $result = $e;
188 Civi::log()->error($e->getMessage());
189 $errorMessage = CRM_Utils_Mail::errorMessage($mailer, $result);
190 CRM_Core_Session::setStatus($testMailStatusMsg . ts('Oops. Your %1 settings are incorrect. No test mail has been sent.', [1 => strtoupper($mailerName)]) . $errorMessage, ts("Mail Not Sent"), "error");
6a488035
TO
191 }
192 }
193 }
194
aaffa79f 195 $mailingBackend = Civi::settings()->get('mailing_backend');
6a488035
TO
196
197 if (!empty($mailingBackend)) {
6e5b5e59 198 $formValues = array_merge($mailingBackend, $formValues);
6a488035
TO
199 }
200
201 // if password is present, encrypt it
202 if (!empty($formValues['smtpPassword'])) {
203 $formValues['smtpPassword'] = CRM_Utils_Crypt::encrypt($formValues['smtpPassword']);
204 }
205
08ef4ddd 206 Civi::settings()->set('mailing_backend', $formValues);
6a488035
TO
207 }
208
209 /**
eceb18cc 210 * Global validation rules for the form.
6a488035 211 *
5173bd95
TO
212 * @param array $fields
213 * Posted values of the form.
6a488035 214 *
177bc889 215 * @return array|bool
a6c01b45 216 * list of errors to be posted back to the form
6a488035 217 */
00be9182 218 public static function formRule($fields) {
6a488035 219 if ($fields['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_SMTP) {
a7488080 220 if (empty($fields['smtpServer'])) {
6a488035
TO
221 $errors['smtpServer'] = 'SMTP Server name is a required field.';
222 }
a7488080 223 if (empty($fields['smtpPort'])) {
6a488035
TO
224 $errors['smtpPort'] = 'SMTP Port is a required field.';
225 }
a7488080
CW
226 if (!empty($fields['smtpAuth'])) {
227 if (empty($fields['smtpUsername'])) {
6a488035
TO
228 $errors['smtpUsername'] = 'If your SMTP server requires authentication please provide a valid user name.';
229 }
a7488080 230 if (empty($fields['smtpPassword'])) {
6a488035
TO
231 $errors['smtpPassword'] = 'If your SMTP server requires authentication, please provide a password.';
232 }
233 }
234 }
235 if ($fields['outBound_option'] == CRM_Mailing_Config::OUTBOUND_OPTION_SENDMAIL) {
236 if (!$fields['sendmail_path']) {
237 $errors['sendmail_path'] = 'Sendmail Path is a required field.';
238 }
239 if (!$fields['sendmail_args']) {
240 $errors['sendmail_args'] = 'Sendmail Argument is a required field.';
241 }
242 }
243
244 return empty($errors) ? TRUE : $errors;
245 }
246
247 /**
c490a46a 248 * Set default values for the form.
6a488035 249 */
00be9182 250 public function setDefaultValues() {
6a488035 251 if (!$this->_defaults) {
be2fb01f 252 $this->_defaults = [];
6a488035 253
aaffa79f 254 $mailingBackend = Civi::settings()->get('mailing_backend');
6a488035
TO
255 if (!empty($mailingBackend)) {
256 $this->_defaults = $mailingBackend;
257
258 if (!empty($this->_defaults['smtpPassword'])) {
259 $this->_defaults['smtpPassword'] = CRM_Utils_Crypt::decrypt($this->_defaults['smtpPassword']);
260 }
261 }
262 else {
263 if (!isset($this->_defaults['smtpServer'])) {
264 $this->_defaults['smtpServer'] = 'localhost';
265 $this->_defaults['smtpPort'] = 25;
266 $this->_defaults['smtpAuth'] = 0;
267 }
268
269 if (!isset($this->_defaults['sendmail_path'])) {
270 $this->_defaults['sendmail_path'] = '/usr/sbin/sendmail';
271 $this->_defaults['sendmail_args'] = '-i';
272 }
273 }
274 }
beac1417 275 $this->_defaults['allow_mail_from_logged_in_contact'] = Civi::settings()->get('allow_mail_from_logged_in_contact');
6a488035
TO
276 return $this->_defaults;
277 }
96025800 278
6a488035 279}