PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
← All changes | app/Services/EmailService.php +81 -4 3.0.2.8 → 3.0.16 View file →
@@ -28,8 +28,14 @@
28 28 * @return bool True on success, false on failure
29 29 */
30 30 public static function send($to, string $subject, string $message, array $headers = [], array $attachments = []): bool
31 31 {
32 + // Archive copy of every Yatra email, if the operator configured one.
33 + // Applied here rather than at each call site so it covers all senders —
34 + // core transactional mail, Pro automation templates and sequences — and
35 + // cannot be forgotten by a sender added later.
36 + $headers = self::withAlwaysBcc($headers);
37 +
32 38 // Check if SMTP is enabled
33 39 $smtp_enabled = SettingsService::isEnabled('smtp_enabled');
34 40
35 41 if ($smtp_enabled) {
@@ -40,8 +46,77 @@
40 46 return self::sendViaWpMail($to, $subject, $message, $headers, $attachments);
41 47 }
42 48
43 49 /**
50 + * Merge the configured always-BCC address into a header list.
51 + *
52 + * Opt-in: with the setting empty nothing is added and the headers are handed
53 + * back untouched, so an operator who never configures it sees no change at
54 + * all. When a template already carries its own Bcc header the two are merged
55 + * and de-duplicated, so an address listed in both places is only copied once.
56 + *
57 + * @param string[] $headers
58 + * @return string[]
59 + */
60 + private static function withAlwaysBcc(array $headers): array
61 + {
62 + // Cc/Bcc configured on the template being sent. Read here rather than at
63 + // the call site because Yatra Pro can take the send over and mail it
64 + // through its own service — both routes end up here.
65 + foreach (TransactionalEmailTemplateService::headersForCurrentDispatch() as $templateHeader) {
66 + $headers[] = $templateHeader;
67 + }
68 +
69 + $configured = TransactionalEmailTemplateService::sanitizeAddressList(
70 + (string) SettingsService::get('email_always_bcc', '')
71 + );
72 +
73 + /**
74 + * Filter the always-BCC recipients for a single send. Return an empty
75 + * array to skip archiving this particular email.
76 + *
77 + * @param string[] $configured
78 + * @param string[] $headers
79 + */
80 + $configured = (array) apply_filters('yatra_email_always_bcc', $configured, $headers);
81 +
82 + if ($configured === []) {
83 + return $headers;
84 + }
85 +
86 + // Fold any Bcc headers already present into the same list so the address
87 + // cannot be added twice, then re-emit a single combined header.
88 + $existing = [];
89 + $kept = [];
90 +
91 + foreach ($headers as $header) {
92 + if (is_string($header) && stripos(trim($header), 'bcc:') === 0) {
93 + $existing = array_merge(
94 + $existing,
95 + TransactionalEmailTemplateService::sanitizeAddressList(trim(substr(trim($header), 4)))
96 + );
97 + continue;
98 + }
99 +
100 + $kept[] = $header;
101 + }
102 +
103 + $all = [];
104 +
105 + foreach (array_merge($existing, $configured) as $address) {
106 + $all[strtolower($address)] = $address;
107 + }
108 +
109 + if ($all === []) {
110 + return $headers;
111 + }
112 +
113 + $kept[] = 'Bcc: ' . implode(', ', array_values($all));
114 +
115 + return $kept;
116 + }
117 +
118 + /**
44 119 * Send email via WordPress wp_mail with custom from address
45 120 */
46 121 private static function sendViaWpMail($to, string $subject, string $message, array $headers, array $attachments): bool
47 122 {
@@ -73,9 +148,8 @@
73 148 $from_name = SettingsService::getString('from_name', get_bloginfo('name'));
74 149
75 150 // Validate required settings
76 151 if (empty($smtp_host) || empty($smtp_username) || empty($smtp_password)) {
77 - error_log('Yatra SMTP: Missing required SMTP configuration');
78 152 return false;
79 153 }
80 154
81 155 try {
@@ -131,9 +205,8 @@
131 205 $mail->send();
132 206 return true;
133 207
134 208 } catch (Exception $e) {
135 - error_log('Yatra SMTP Error: ' . $mail->ErrorInfo);
136 209 return false;
137 210 }
138 211 }
139 212
@@ -162,9 +235,9 @@
162 235 {
163 236 $from_email = SettingsService::getString('from_email', '');
164 237 return !empty($from_email) ? $from_email : $email;
165 238 }
166 -
239 +
167 240 /**
168 241 * Custom from name filter
169 242 */
170 243 public static function customFromName($name)
@@ -215,9 +288,13 @@
215 288
216 289 } catch (Exception $e) {
217 290 return [
218 291 'success' => false,
219 - 'message' => sprintf(__('SMTP connection failed: %s', 'yatra'), $e->getMessage())
292 + 'message' => sprintf(
293 + /* translators: %s: SMTP error message. */
294 + __('SMTP connection failed: %s', 'yatra'),
295 + $e->getMessage()
296 + )
220 297 ];
221 298 }
222 299 }
223 300 }