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 +75 -0 3.0.7 → 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) {
@@ -39,8 +45,77 @@
39 45 // Use default WordPress wp_mail
40 46 return self::sendViaWpMail($to, $subject, $message, $headers, $attachments);
41 47 }
42 48
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 +
43 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