FluentSMTP – WP Mail SMTP, Amazon SES, SendGrid, MailGun and Any SMTP Connector Plugin - Version 1.1.0

Version Description

(Date: April 25, 2021) = * Fix Error Handling Issues * DataBase Query Optimizations * Amazon SES Connection Optimization * UI Improvement * VueJS loading improvements

Download this release

Release Info

Developer techjewel
Plugin Icon FluentSMTP – WP Mail SMTP, Amazon SES, SendGrid, MailGun and Any SMTP Connector Plugin
Version 1.1.0
Comparing to
See all releases

Code changes from version 1.0.1 to 1.1.0

Files changed (44) hide show
  1. app/Functions/helpers.php +10 -3
  2. app/Hooks/Handlers/AdminMenuHandler.php +64 -6
  3. app/Hooks/actions.php +2 -1
  4. app/Http/Controllers/SettingsController.php +69 -1
  5. app/Http/routes.php +2 -0
  6. app/Models/Logger.php +60 -43
  7. app/Models/Model.php +21 -0
  8. app/Services/Mailer/BaseHandler.php +16 -15
  9. app/Services/Mailer/FluentPHPMailer.php +0 -6
  10. app/Services/Mailer/Providers/AmazonSes/Handler.php +8 -114
  11. app/Services/Mailer/Providers/AmazonSes/SimpleEmailService.php +640 -596
  12. app/Services/Mailer/Providers/AmazonSes/SimpleEmailServiceMessage.php +2 -0
  13. app/Services/Mailer/Providers/DefaultMail/Handler.php +3 -10
  14. app/Services/Mailer/Providers/Mailgun/Handler.php +46 -76
  15. app/Services/Mailer/Providers/PepiPost/Handler.php +27 -85
  16. app/Services/Mailer/Providers/SendGrid/Handler.php +22 -80
  17. app/Services/Mailer/Providers/SendInBlue/Handler.php +23 -56
  18. app/Services/Mailer/Providers/Smtp/Handler.php +15 -23
  19. app/Services/Mailer/Providers/Smtp/ValidatorTrait.php +21 -9
  20. app/Services/Mailer/Providers/SparkPost/Handler.php +23 -71
  21. app/Services/Mailer/Providers/TransMail/Handler.php +250 -0
  22. app/Services/Mailer/Providers/TransMail/ValidatorTrait.php +39 -0
  23. app/Services/Mailer/Providers/config.php +3 -2
  24. app/Services/wpfluent/autoload.php +27 -0
  25. app/Services/wpfluent/libs/viocon/autoload.php +24 -0
  26. app/Services/wpfluent/libs/viocon/src/Viocon/AliasFacade.php +47 -0
  27. app/Services/wpfluent/libs/viocon/src/Viocon/Container.php +140 -0
  28. app/Services/wpfluent/libs/viocon/src/Viocon/VioconException.php +7 -0
  29. app/Services/wpfluent/src/AliasFacade.php +43 -0
  30. app/Services/wpfluent/src/Connection.php +186 -0
  31. app/Services/wpfluent/src/EventHandler.php +98 -0
  32. app/Services/wpfluent/src/Exception.php +6 -0
  33. app/Services/wpfluent/src/QueryBuilder/Adapters/BaseAdapter.php +545 -0
  34. app/Services/wpfluent/src/QueryBuilder/Adapters/Mysql.php +9 -0
  35. app/Services/wpfluent/src/QueryBuilder/JoinBuilder.php +45 -0
  36. app/Services/wpfluent/src/QueryBuilder/NestedCriteria.php +20 -0
  37. app/Services/wpfluent/src/QueryBuilder/QueryBuilderHandler.php +1154 -0
  38. app/Services/wpfluent/src/QueryBuilder/QueryObject.php +102 -0
  39. app/Services/wpfluent/src/QueryBuilder/Raw.php +34 -0
  40. app/Services/wpfluent/src/QueryBuilder/Transaction.php +27 -0
  41. app/Services/wpfluent/src/QueryBuilder/TransactionHaltException.php +7 -0
  42. app/Services/wpfluent/wpfluent.php +36 -0
  43. assets/admin/css/fluent-mail-admin.css +1 -1
  44. assets/admin/js/vendor.js +0 -1
app/Functions/helpers.php CHANGED
@@ -140,12 +140,19 @@ if (!function_exists('fluentMailGetProvider')) {
140
 
141
  $mappings = $manager->getSettings('mappings');
142
 
 
 
143
  if (isset($mappings[$fromEmail])) {
144
  $connectionId = $mappings[$fromEmail];
145
  $connections = $manager->getSettings('connections');
146
- $connection = $connections[$connectionId]['provider_settings'];
147
- } else {
148
- if ($connection = fluentMailDefaultConnection()) {
 
 
 
 
 
149
  $connection['force_from_email_id'] = $connection['sender_email'];
150
  }
151
  }
140
 
141
  $mappings = $manager->getSettings('mappings');
142
 
143
+ $connection = false;
144
+
145
  if (isset($mappings[$fromEmail])) {
146
  $connectionId = $mappings[$fromEmail];
147
  $connections = $manager->getSettings('connections');
148
+ if(isset($connections[$connectionId])) {
149
+ $connection = $connections[$connectionId]['provider_settings'];
150
+ }
151
+ }
152
+
153
+ if(!$connection) {
154
+ $connection = fluentMailDefaultConnection();
155
+ if($connection) {
156
  $connection['force_from_email_id'] = $connection['sender_email'];
157
  }
158
  }
app/Hooks/Handlers/AdminMenuHandler.php CHANGED
@@ -16,6 +16,16 @@ class AdminMenuHandler
16
  }
17
 
18
  public function addFluentMailMenu()
 
 
 
 
 
 
 
 
 
 
19
  {
20
  $title = $this->app->applyCustomFilters('admin-menu-title', __('Fluent SMTP', 'fluent-smtp'));
21
 
@@ -32,12 +42,41 @@ class AdminMenuHandler
32
 
33
  public function renderApp()
34
  {
35
- $this->enqueueAssets();
36
  $this->app->view->render('admin.menu');
37
  }
38
 
39
- private function enqueueAssets()
40
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  wp_enqueue_script(
42
  'fluent_mail_admin_app_boot',
43
  fluentMailMix('admin/js/boot.js'),
@@ -53,6 +92,8 @@ class AdminMenuHandler
53
  'fluent_mail_admin_app', fluentMailMix('admin/css/fluent-mail-admin.css'), [], FLUENTMAIL_PLUGIN_VERSION
54
  );
55
 
 
 
56
  wp_localize_script('fluent_mail_admin_app_boot', 'FluentMailAdmin', [
57
  'slug' => FLUENTMAIL,
58
  'brand_logo' => esc_url(fluentMailMix('images/logo.svg')),
@@ -60,6 +101,8 @@ class AdminMenuHandler
60
  'settings' => $this->getMailerSettings(),
61
  'has_fluentcrm' => defined('FLUENTCRM'),
62
  'has_fluentform' => defined('FLUENTFORM'),
 
 
63
  'has_ninja_tables' => defined('NINJA_TABLES_VERSION'),
64
  'disable_recommendation' => apply_filters('fluentmail_disable_recommendation', false),
65
  'plugin_url' => 'https://fluentsmtp.com/?utm_source=wp&utm_medium=install&utm_campaign=dashboard'
@@ -108,28 +151,43 @@ class AdminMenuHandler
108
 
109
  global $wp_version;
110
 
111
- $requireUpdate = version_compare($wp_version,'5.5', '<');
112
 
113
- if($requireUpdate) { ?>
114
  <div class="notice notice-warning">
115
  <p>
116
  <?php echo sprintf(__('WordPress version 5.5 or greater is required for FluentSMTP. You are using version %s currently. Please update your WordPress Core to use FluentSMTP Plugin.', 'fluent-smtp'), $wp_version); ?>
117
  </p>
118
  </div>
119
- <?php } else if(empty($connections)) {
120
  ?>
121
  <div class="notice notice-warning">
122
  <p>
123
  <?php _e('FluentSMTP requires to configure properly. Please configure FluentSMTP to make your email delivery works.', 'fluent-smtp'); ?>
124
  </p>
125
  <p>
126
- <a href="<?php echo admin_url('options-general.php?page=fluent-mail#/'); ?>" class="button button-primary">
 
127
  <?php _e('Configure FluentSMTP', 'fluent-smtp'); ?>
128
  </a>
129
  </p>
130
  </div>
131
  <?php
132
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
 
134
  }
135
  }
16
  }
17
 
18
  public function addFluentMailMenu()
19
+ {
20
+ add_action('admin_menu', array($this, 'addMenu'));
21
+
22
+ if (isset($_GET['page']) && $_GET['page'] == 'fluent-mail' && is_admin()) {
23
+ add_action('admin_enqueue_scripts', array($this, 'enqueueAssets'));
24
+ }
25
+
26
+ }
27
+
28
+ public function addMenu()
29
  {
30
  $title = $this->app->applyCustomFilters('admin-menu-title', __('Fluent SMTP', 'fluent-smtp'));
31
 
42
 
43
  public function renderApp()
44
  {
 
45
  $this->app->view->render('admin.menu');
46
  }
47
 
48
+ public function enqueueAssets()
49
  {
50
+ add_action('wp_print_scripts', function () {
51
+ $isSkip = apply_filters('fluentsmtp_skip_no_conflict', false);
52
+
53
+ if ($isSkip) {
54
+ return;
55
+ }
56
+
57
+ global $wp_scripts;
58
+ if (!$wp_scripts) {
59
+ return;
60
+ }
61
+
62
+ $themeUrl = content_url('themes');
63
+ $pluginUrl = plugins_url();
64
+ foreach ($wp_scripts->queue as $script) {
65
+ $src = $wp_scripts->registered[$script]->src;
66
+ $isMatched = strpos($src, $pluginUrl) !== false && !strpos($src, 'fluent-smtp') !== false;
67
+ if (!$isMatched) {
68
+ continue;
69
+ }
70
+
71
+ $isMatched = strpos($src, $themeUrl) !== false;
72
+
73
+ if ($isMatched) {
74
+ wp_dequeue_script($wp_scripts->registered[$script]->handle);
75
+ }
76
+ }
77
+
78
+ }, 1);
79
+
80
  wp_enqueue_script(
81
  'fluent_mail_admin_app_boot',
82
  fluentMailMix('admin/js/boot.js'),
92
  'fluent_mail_admin_app', fluentMailMix('admin/css/fluent-mail-admin.css'), [], FLUENTMAIL_PLUGIN_VERSION
93
  );
94
 
95
+ $user = get_user_by('ID', get_current_user_id());
96
+
97
  wp_localize_script('fluent_mail_admin_app_boot', 'FluentMailAdmin', [
98
  'slug' => FLUENTMAIL,
99
  'brand_logo' => esc_url(fluentMailMix('images/logo.svg')),
101
  'settings' => $this->getMailerSettings(),
102
  'has_fluentcrm' => defined('FLUENTCRM'),
103
  'has_fluentform' => defined('FLUENTFORM'),
104
+ 'user_email' => $user->user_email,
105
+ 'require_optin' => $this->isRequireOptin(),
106
  'has_ninja_tables' => defined('NINJA_TABLES_VERSION'),
107
  'disable_recommendation' => apply_filters('fluentmail_disable_recommendation', false),
108
  'plugin_url' => 'https://fluentsmtp.com/?utm_source=wp&utm_medium=install&utm_campaign=dashboard'
151
 
152
  global $wp_version;
153
 
154
+ $requireUpdate = version_compare($wp_version, '5.5', '<');
155
 
156
+ if ($requireUpdate) { ?>
157
  <div class="notice notice-warning">
158
  <p>
159
  <?php echo sprintf(__('WordPress version 5.5 or greater is required for FluentSMTP. You are using version %s currently. Please update your WordPress Core to use FluentSMTP Plugin.', 'fluent-smtp'), $wp_version); ?>
160
  </p>
161
  </div>
162
+ <?php } else if (empty($connections)) {
163
  ?>
164
  <div class="notice notice-warning">
165
  <p>
166
  <?php _e('FluentSMTP requires to configure properly. Please configure FluentSMTP to make your email delivery works.', 'fluent-smtp'); ?>
167
  </p>
168
  <p>
169
+ <a href="<?php echo admin_url('options-general.php?page=fluent-mail#/'); ?>"
170
+ class="button button-primary">
171
  <?php _e('Configure FluentSMTP', 'fluent-smtp'); ?>
172
  </a>
173
  </p>
174
  </div>
175
  <?php
176
  }
177
+ }
178
+
179
+ public function isRequireOptin()
180
+ {
181
+ $opted = get_option('_fluentsmtp_sub_update');
182
+ if($opted) {
183
+ return 'no';
184
+ }
185
+ // check if dismissed
186
+ $dismissedStamp = get_option('_fluentsmtp_dismissed_timestamp');
187
+ if($dismissedStamp && (time() - $dismissedStamp) < 30 * 24 * 60 * 60) {
188
+ return 'no';
189
+ }
190
 
191
+ return 'yes';
192
  }
193
  }
app/Hooks/actions.php CHANGED
@@ -1,8 +1,9 @@
1
  <?php
2
 
 
 
3
  $app->addCustomAction('handle_exception', 'ExceptionHandler@handle');
4
 
5
- $app->addAction('admin_menu', 'AdminMenuHandler@addFluentMailMenu');
6
 
7
  $app->addAction('admin_notices', 'AdminMenuHandler@maybeAdminNotice');
8
 
1
  <?php
2
 
3
+ (new \FluentMail\App\Hooks\Handlers\AdminMenuHandler($app))->addFluentMailMenu();
4
+
5
  $app->addCustomAction('handle_exception', 'ExceptionHandler@handle');
6
 
 
7
 
8
  $app->addAction('admin_notices', 'AdminMenuHandler@maybeAdminNotice');
9
 
app/Http/Controllers/SettingsController.php CHANGED
@@ -153,7 +153,7 @@ class SettingsController extends Controller
153
  return $this->sendError([
154
  'message' => $response->get_error_message(),
155
  'errors' => $response->get_error_data()
156
- ], $response->get_error_code());
157
  }
158
 
159
  public function validateConnection($provider, $connection)
@@ -357,4 +357,72 @@ class SettingsController extends Controller
357
  }
358
  }
359
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  }
153
  return $this->sendError([
154
  'message' => $response->get_error_message(),
155
  'errors' => $response->get_error_data()
156
+ ], 423);
157
  }
158
 
159
  public function validateConnection($provider, $connection)
357
  }
358
  }
359
  }
360
+
361
+ public function subscribe()
362
+ {
363
+ $email = sanitize_text_field($_REQUEST['email']);
364
+ if(!is_email($email)) {
365
+ return $this->sendError([
366
+ 'message' => 'Sorry! The provider email is not valid'
367
+ ], 423);
368
+ }
369
+
370
+ $shareEssentials = 'no';
371
+
372
+ if($_REQUEST['share_essentials'] == 'yes') {
373
+ update_option('_fluentsmtp_sub_update', 'shared', 'no');
374
+ $shareEssentials = 'yes';
375
+ } else {
376
+ update_option('_fluentsmtp_sub_update', 'yes', 'no');
377
+ }
378
+
379
+ $this->pushData($email, $shareEssentials);
380
+
381
+ return $this->sendSuccess([
382
+ 'message' => 'You are subscribed to plugin update and monthly tips'
383
+ ]);
384
+ }
385
+
386
+ public function subscribeDismiss()
387
+ {
388
+ update_option('_fluentsmtp_dismissed_timestamp', time(), 'no');
389
+
390
+ return $this->sendSuccess([
391
+ 'message' => 'success'
392
+ ]);
393
+ }
394
+
395
+ private function pushData($optinEmail, $shareEssentials)
396
+ {
397
+ $user = get_user_by('ID', get_current_user_id());
398
+
399
+ $data = [
400
+ 'answers' => [
401
+ 'website' => site_url(),
402
+ 'email' => $optinEmail,
403
+ 'first_name' => $user->first_name,
404
+ 'last_name' => $user->last_name,
405
+ 'name' => $user->display_name,
406
+ 'essential' => $shareEssentials
407
+ ],
408
+ 'questions' => [
409
+ 'website' => 'website',
410
+ 'first_name' => 'first_name',
411
+ 'last_name' => 'last_name',
412
+ 'email' => 'email',
413
+ 'name' => 'name',
414
+ 'essential' => 'essential'
415
+ ],
416
+ 'user' => [
417
+ 'email' => $optinEmail
418
+ ],
419
+ 'fb_capture' => 1,
420
+ 'form_id' => 67
421
+ ];
422
+
423
+ $url = add_query_arg($data, 'https://wpmanageninja.com/');
424
+
425
+ wp_remote_post($url);
426
+ }
427
+
428
  }
app/Http/routes.php CHANGED
@@ -10,6 +10,8 @@ $app->post('/misc-settings', 'SettingsController@storeMiscSettings');
10
  $app->post('/settings/delete', 'SettingsController@delete');
11
  $app->post('/settings/misc', 'SettingsController@storeGlobals');
12
  $app->post('/settings/test', 'SettingsController@sendTestEmil');
 
 
13
  $app->get('settings/connection_info', 'SettingsController@getConnectionInfo');
14
 
15
  $app->get('/logs', 'LoggerController@get');
10
  $app->post('/settings/delete', 'SettingsController@delete');
11
  $app->post('/settings/misc', 'SettingsController@storeGlobals');
12
  $app->post('/settings/test', 'SettingsController@sendTestEmil');
13
+ $app->post('/settings/subscribe', 'SettingsController@subscribe');
14
+ $app->post('/settings/subscribe-dismiss', 'SettingsController@subscribeDismiss');
15
  $app->get('settings/connection_info', 'SettingsController@getConnectionInfo');
16
 
17
  $app->get('/logs', 'LoggerController@get');
app/Models/Logger.php CHANGED
@@ -3,7 +3,6 @@
3
  namespace FluentMail\App\Models;
4
 
5
  use Exception;
6
- use FluentMail\App\Services\Mailer\EmailQueueProcessor;
7
 
8
  class Logger extends Model
9
  {
@@ -42,45 +41,64 @@ class Logger extends Model
42
 
43
  public function get($data)
44
  {
45
- foreach (['date', 'daterange'] as $field) {
46
- if ($data['filter_by'] == $field) {
47
- $data['filter_by'] = 'created_at';
48
- }
49
- }
50
-
51
- $total = 0;
52
- $page = intval($data['page']);
53
- $perPage = intval($data['per_page']);
54
  $offset = ($page - 1) * $perPage;
55
 
56
- list($where, $args) = $this->buildWhere($data);
 
 
 
57
 
58
- $query = $this->db->prepare(
59
- "SELECT * FROM `{$this->table}` {$where} ORDER BY id DESC LIMIT %d OFFSET %d",
60
- array_merge($args, [$perPage, $offset])
61
- );
62
 
 
 
 
 
 
 
 
63
 
64
- $result = $this->db->get_results($query);
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
- if ($this->db->num_rows) {
67
- $total = (int)$this->db->get_var(
68
- $this->db->prepare(
69
- "SELECT COUNT(id) FROM `{$this->table}` {$where}", $args
70
- )
71
- );
 
 
 
72
  }
73
 
74
- $result = $this->formatResult($result);
75
 
76
- return [
77
- 'data' => $result,
78
- 'total' => $total
79
- ];
80
  }
81
 
82
  protected function buildWhere($data)
83
  {
 
 
84
  if (isset($data['filter_by_value'])) {
85
  $where[$data['filter_by']] = $data['filter_by_value'];
86
  }
@@ -175,9 +193,9 @@ class Logger extends Model
175
  'created_at' => current_time('mysql')
176
  ]);
177
 
178
- $this->db->insert($this->table, $data);
 
179
 
180
- return $this->db->insert_id;
181
  } catch (Exception $e) {
182
  return $e;
183
  }
@@ -189,14 +207,15 @@ class Logger extends Model
189
  return $this->db->query("TRUNCATE TABLE {$this->table}");
190
  }
191
 
192
- $placeHolders = array_fill(0, count($id), '%d');
193
 
194
- $query = $this->db->prepare(
195
- "DELETE FROM {$this->table} WHERE id IN (" . implode(',', $placeHolders) . ")",
196
- $id
197
- );
 
198
 
199
- return $this->db->query($query);
200
  }
201
 
202
  public function navigate($data)
@@ -259,18 +278,16 @@ class Logger extends Model
259
 
260
  public function find($id)
261
  {
262
- $query = $this->db->prepare(
263
- "SELECT * FROM `{$this->table}` WHERE `id` = %d",
264
- [$id]
265
- );
266
 
267
- $row = $this->db->get_row($query, ARRAY_A);
 
 
268
 
269
- $row['extra'] = maybe_unserialize($row['extra']);
270
 
271
- $row['response'] = maybe_unserialize($row['response']);
272
 
273
- return $row;
274
  }
275
 
276
  public function resendEmailFromLog($id, $type = 'retry')
3
  namespace FluentMail\App\Models;
4
 
5
  use Exception;
 
6
 
7
  class Logger extends Model
8
  {
41
 
42
  public function get($data)
43
  {
44
+ $db = $this->getDb();
45
+ $page = isset($data['page']) ? intval($data['page']) : 1;
46
+ $perPage = isset($data['per_page']) ? intval($data['per_page']) : 15;
 
 
 
 
 
 
47
  $offset = ($page - 1) * $perPage;
48
 
49
+ $query = $db->table(FLUENT_MAIL_DB_PREFIX . 'email_logs')
50
+ ->limit($page)
51
+ ->offset($offset)
52
+ ->orderBy('id', 'DESC');
53
 
54
+ $filterColumn = isset($data['filter_by']) ? sanitize_text_field($data['filter_by']) : false;
55
+ $filterValue = $data['filter_by_value'];
 
 
56
 
57
+ if($filterColumn && $filterValue) {
58
+ if($filterColumn == 'daterange' && is_array($filterValue)) {
59
+ $query->whereBetween('created_at', $filterValue[0], $filterValue[1]);
60
+ } else if($filterValue) {
61
+ $query->where($filterColumn, $filterValue);
62
+ }
63
+ }
64
 
65
+ if(!empty($data['query'])) {
66
+ $search = trim(sanitize_text_field($data['query']));
67
+ $query->where(function ($q) use ($search) {
68
+ $searchColumns = $this->searchables;
69
+
70
+ $columnSearch = false;
71
+ if(strpos($search, ':')) {
72
+ $searchArray = explode(':', $search);
73
+ $column = array_shift($searchArray);
74
+ if(in_array($column, $this->fillables)) {
75
+ $columnSearch = true;
76
+ $q->where($column, 'LIKE', '%'.trim(implode(':', $searchArray)).'%');
77
+ }
78
+ }
79
 
80
+ if(!$columnSearch) {
81
+ $firstColumn = array_shift($searchColumns);
82
+ $q->where($firstColumn, 'LIKE', '%'.$search.'%');
83
+ foreach ($searchColumns as $column) {
84
+ $q->orWhere($column, 'LIKE', '%'.$search.'%');
85
+ }
86
+ }
87
+
88
+ });
89
  }
90
 
91
+ $result = $query->paginate();
92
 
93
+ $result['data'] = $this->formatResult($result['data']);
94
+
95
+ return $result;
 
96
  }
97
 
98
  protected function buildWhere($data)
99
  {
100
+ $where = [];
101
+
102
  if (isset($data['filter_by_value'])) {
103
  $where[$data['filter_by']] = $data['filter_by_value'];
104
  }
193
  'created_at' => current_time('mysql')
194
  ]);
195
 
196
+ return $this->getDb()->table(FLUENT_MAIL_DB_PREFIX . 'email_logs')
197
+ ->insert($data);
198
 
 
199
  } catch (Exception $e) {
200
  return $e;
201
  }
207
  return $this->db->query("TRUNCATE TABLE {$this->table}");
208
  }
209
 
210
+ $ids = array_filter($id, 'intval');
211
 
212
+ if($ids) {
213
+ return $this->getDb()->table(FLUENT_MAIL_DB_PREFIX . 'email_logs')
214
+ ->whereIn('id', $ids)
215
+ ->delete();
216
+ }
217
 
218
+ return false;
219
  }
220
 
221
  public function navigate($data)
278
 
279
  public function find($id)
280
  {
 
 
 
 
281
 
282
+ $row = $this->getDb()->table(FLUENT_MAIL_DB_PREFIX . 'email_logs')
283
+ ->where('id', $id)
284
+ ->first();
285
 
286
+ $row->extra = maybe_unserialize($row->extra);
287
 
288
+ $row->response = maybe_unserialize($row->response);
289
 
290
+ return (array) $row;
291
  }
292
 
293
  public function resendEmailFromLog($id, $type = 'retry')
app/Models/Model.php CHANGED
@@ -22,4 +22,25 @@ class Model
22
  {
23
  return call_user_func_array([$this->db, $method], $params);
24
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  }
22
  {
23
  return call_user_func_array([$this->db, $method], $params);
24
  }
25
+
26
+ public function getDb()
27
+ {
28
+ if(function_exists('wpFluent')) {
29
+ return wpFluent();
30
+ }
31
+
32
+ static $wpFluent;
33
+
34
+ if (! $wpFluent) {
35
+
36
+ require_once(FLUENTMAIL_PLUGIN_PATH .' app/Services/wpfluent/autoload.php');
37
+ global $wpdb;
38
+ $connection = new \WpFluent\Connection($wpdb, ['prefix' => $wpdb->prefix]);
39
+
40
+ $wpFluent = new \WpFluent\QueryBuilder\QueryBuilderHandler($connection);
41
+ }
42
+
43
+ return $wpFluent;
44
+
45
+ }
46
  }
app/Services/Mailer/BaseHandler.php CHANGED
@@ -46,6 +46,7 @@ class BaseHandler
46
 
47
  public function setSettings($settings)
48
  {
 
49
  $this->settings = $settings;
50
 
51
  return $this;
@@ -250,32 +251,27 @@ class BaseHandler
250
 
251
  public function handleResponse($response)
252
  {
253
- if (is_wp_error($response)) {
254
- $message = 'Oops!';
255
-
256
  $code = $response->get_error_code();
257
 
258
  if (!is_numeric($code)) {
259
- $message = ucwords(str_replace(['_', '-'], ' ', $code));
260
  $code = 400;
261
  }
262
 
263
- $response = [
 
 
264
  'code' => $code,
265
  'message' => $message,
266
  'errors' => $response->get_error_messages()
267
  ];
268
 
269
- $this->processResponse($response, false);
270
 
271
- $this->fireWPMailFailedAction($response);
272
 
273
  } else {
274
- if ($this->isEmailSent()) {
275
- return $this->handleSuccess();
276
- } else {
277
- return $this->handleFailure();
278
- }
279
  }
280
  }
281
 
@@ -321,9 +317,14 @@ class BaseHandler
321
  $code = is_numeric($data['code']) ? $data['code'] : 400;
322
  $code = strlen($code) < 3 ? 400 : $code;
323
 
324
- $this->app->doAction('wp_mail_failed', new \WP_Error(
325
- $code, $data['message'], $data['errors']
326
- ));
 
 
 
 
 
327
  }
328
 
329
  protected function updatedLog($id, $data)
46
 
47
  public function setSettings($settings)
48
  {
49
+
50
  $this->settings = $settings;
51
 
52
  return $this;
251
 
252
  public function handleResponse($response)
253
  {
254
+ if ( is_wp_error($response) ) {
 
 
255
  $code = $response->get_error_code();
256
 
257
  if (!is_numeric($code)) {
 
258
  $code = 400;
259
  }
260
 
261
+ $message = $response->get_error_message();
262
+
263
+ $errorResponse = [
264
  'code' => $code,
265
  'message' => $message,
266
  'errors' => $response->get_error_messages()
267
  ];
268
 
269
+ $this->processResponse($errorResponse, false);
270
 
271
+ throw new \PHPMailer\PHPMailer\Exception($message, $code);
272
 
273
  } else {
274
+ return $this->processResponse($response, true);
 
 
 
 
275
  }
276
  }
277
 
317
  $code = is_numeric($data['code']) ? $data['code'] : 400;
318
  $code = strlen($code) < 3 ? 400 : $code;
319
 
320
+ $mail_error_data['phpmailer_exception_code'] = $code;
321
+ $mail_error_data['errors'] = $data['errors'];
322
+
323
+ $error = new \WP_Error(
324
+ $code, $data['message'], $mail_error_data
325
+ );
326
+
327
+ $this->app->doAction('wp_mail_failed', $error);
328
  }
329
 
330
  protected function updatedLog($id, $data)
app/Services/Mailer/FluentPHPMailer.php CHANGED
@@ -43,12 +43,6 @@ class FluentPHPMailer
43
  $this->phpMailer->{$key} = $value;
44
  }
45
 
46
- // public static function __callStatic($method, $params)
47
- // {
48
- // return call_user_func_array([$this->phpMailer, $method], $params);
49
- // }
50
- //
51
-
52
  public function __call($method, $params)
53
  {
54
  return call_user_func_array([$this->phpMailer, $method], $params);
43
  $this->phpMailer->{$key} = $value;
44
  }
45
 
 
 
 
 
 
 
46
  public function __call($method, $params)
47
  {
48
  return call_user_func_array([$this->phpMailer, $method], $params);
app/Services/Mailer/Providers/AmazonSes/Handler.php CHANGED
@@ -2,15 +2,8 @@
2
 
3
  namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
4
 
5
- use WP_Error as WPError;
6
  use FluentMail\App\Models\Settings;
7
- use FluentMail\Includes\Support\Arr;
8
- use FluentMail\Includes\Core\Application;
9
- use FluentMail\App\Services\Mailer\Manager;
10
  use FluentMail\App\Services\Mailer\BaseHandler;
11
- use FluentMail\App\Services\Mailer\Providers\AmazonSes\ValidatorTrait;
12
- use FluentMail\App\Services\Mailer\Providers\AmazonSes\SimpleEmailService;
13
- use FluentMail\App\Services\Mailer\Providers\AmazonSes\SimpleEmailServiceMessage;
14
 
15
  class Handler extends BaseHandler
16
  {
@@ -24,52 +17,23 @@ class Handler extends BaseHandler
24
 
25
  public function send()
26
  {
27
- if ($this->preSend()) {
28
  $this->client = new SimpleEmailServiceMessage;
29
  return $this->postSend();
30
  }
31
 
32
- $this->handleFailure(new Exception('Something went wrong!', 0));
33
  }
34
 
35
  public function postSend()
36
  {
37
-
38
- list($text, $html) = $this->getBody();
39
-
40
- $this->client->setFrom($this->getFrom());
41
- $this->client->addReplyTo($this->getReplyTo());
42
- $this->client->addTo($this->getTo());
43
- $this->client->addCC($this->getCarbonCopy());
44
- $this->client->addBCC($this->getBlindCarbonCopy());
45
- $this->client->setSubject($this->getSubject());
46
-
47
- if ($this->phpMailer->ContentType == 'text/plain') {
48
- if (!$text) {
49
- $text = $html;
50
- }
51
- $this->client->setMessageFromString($text);
52
- } else {
53
- $this->client->setMessageFromString($text, $html);
54
- }
55
-
56
- if (!empty($this->getParam('attachments'))) {
57
- foreach ($this->getAttachments() as $attachment) {
58
- $this->client->addAttachmentFromData(
59
- $attachment['name'], $attachment['content'], $attachment['type']
60
- );
61
- }
62
- }
63
-
64
- foreach ($this->getCustomEmailHeaders() as $header) {
65
- $this->client->addCustomHeader($header);
66
- }
67
 
68
  $connectionSettings = $this->filterConnectionVars($this->getSetting());
69
 
70
  $ses = fluentMailSesConnection($connectionSettings);
71
 
72
- $this->response = $ses->sendEmail($this->client, static::RAW_REQUEST);
73
 
74
  return $this->handleResponse($this->response);
75
  }
@@ -182,78 +146,6 @@ class Handler extends BaseHandler
182
  return 'email.' . $this->getSetting('region') . '.amazonaws.com';
183
  }
184
 
185
- protected function isEmailSent()
186
- {
187
- $isSent = false;
188
-
189
- if (is_array($this->response)) {
190
- $isSent = array_key_exists(
191
- 'MessageId', $this->response
192
- ) && array_key_exists(
193
- 'RequestId', $this->response
194
- );
195
- }
196
-
197
- return $isSent;
198
- }
199
-
200
- public function handleSuccess()
201
- {
202
- return $this->processResponse([
203
- 'response' => $this->response
204
- ], true);
205
- }
206
-
207
- public function handleFailure()
208
- {
209
- $response = $this->getResponseError();
210
-
211
- $this->processResponse(['response' => $response], false);
212
-
213
- $this->fireWPMailFailedAction($response);
214
- }
215
-
216
- protected function getResponseError()
217
- {
218
- $response = (array) $this->response;
219
-
220
- if (!($response = array_filter($response))) {
221
- return [
222
- 'errors' => ['Unknown Error'],
223
- 'code' => 400,
224
- 'message' => 'Something went wrong.'
225
- ];
226
- }
227
-
228
- $error = $response['error'];
229
-
230
- if (isset($error['Error'])) {
231
- $error = $error['Error'];
232
- }
233
-
234
- if (isset($error['Type'])) {
235
- $errors[] = 'Type: ' . $error['Type'];
236
- }
237
-
238
- if (isset($response['error']['RequestId'])) {
239
- $errors[] = 'Request-ID: ' . $response['error']['RequestId'];
240
- }
241
-
242
- if (isset($error['Message'])) {
243
- $errors[] = $error['Message'];
244
- }
245
-
246
- if (isset($error['message'])) {
247
- $errors[] = $error['message'];
248
- }
249
-
250
- return [
251
- 'errors' => $errors,
252
- 'code' => $response['code'],
253
- 'message' => $error['Code']
254
- ];
255
- }
256
-
257
  public function getValidSenders($config)
258
  {
259
  $config = $this->filterConnectionVars($config);
@@ -269,11 +161,13 @@ class Handler extends BaseHandler
269
 
270
  $validSenders = $ses->listVerifiedEmailAddresses();
271
 
 
 
272
  if($validSenders && isset($validSenders['Addresses'])) {
273
- return $validSenders['Addresses'];
274
  }
275
 
276
- return [];
277
  }
278
 
279
  public function getConnectionInfo($connection)
2
 
3
  namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
4
 
 
5
  use FluentMail\App\Models\Settings;
 
 
 
6
  use FluentMail\App\Services\Mailer\BaseHandler;
 
 
 
7
 
8
  class Handler extends BaseHandler
9
  {
17
 
18
  public function send()
19
  {
20
+ if ($this->preSend() && $this->phpMailer->preSend()) {
21
  $this->client = new SimpleEmailServiceMessage;
22
  return $this->postSend();
23
  }
24
 
25
+ return $this->handleResponse(new \WP_Error(423, 'Something went wrong!', []) );
26
  }
27
 
28
  public function postSend()
29
  {
30
+ $mime = chunk_split(base64_encode($this->phpMailer->getSentMIMEMessage()), 76, "\n");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
  $connectionSettings = $this->filterConnectionVars($this->getSetting());
33
 
34
  $ses = fluentMailSesConnection($connectionSettings);
35
 
36
+ $this->response = $ses->sendRawEmail($mime);
37
 
38
  return $this->handleResponse($this->response);
39
  }
146
  return 'email.' . $this->getSetting('region') . '.amazonaws.com';
147
  }
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  public function getValidSenders($config)
150
  {
151
  $config = $this->filterConnectionVars($config);
161
 
162
  $validSenders = $ses->listVerifiedEmailAddresses();
163
 
164
+ $addresses = [];
165
+
166
  if($validSenders && isset($validSenders['Addresses'])) {
167
+ $addresses = $validSenders['Addresses'];
168
  }
169
 
170
+ return apply_filters('fluentsmtp_ses_valid_senders', $addresses, $config);
171
  }
172
 
173
  public function getConnectionInfo($connection)
app/Services/Mailer/Providers/AmazonSes/SimpleEmailService.php CHANGED
@@ -3,111 +3,111 @@
3
  namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
4
 
5
  /**
6
- *
7
- * Copyright (c) 2014, Daniel Zahariev.
8
- * Copyright (c) 2011, Dan Myers.
9
- * Parts copyright (c) 2008, Donovan Schonknecht.
10
- * All rights reserved.
11
- *
12
- * Redistribution and use in source and binary forms, with or without
13
- * modification, are permitted provided that the following conditions are met:
14
- *
15
- * - Redistributions of source code must retain the above copyright notice,
16
- * this list of conditions and the following disclaimer.
17
- * - Redistributions in binary form must reproduce the above copyright
18
- * notice, this list of conditions and the following disclaimer in the
19
- * documentation and/or other materials provided with the distribution.
20
- *
21
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
- * POSSIBILITY OF SUCH DAMAGE.
32
- *
33
- * This is a modified BSD license (the third clause has been removed).
34
- * The BSD license may be found here:
35
- * http://www.opensource.org/licenses/bsd-license.php
36
- *
37
- * Amazon Simple Email Service is a trademark of Amazon.com, Inc. or its affiliates.
38
- *
39
- * SimpleEmailService is based on Donovan Schonknecht's Amazon S3 PHP class, found here:
40
- * http://undesigned.org.za/2007/10/22/amazon-s3-php-class
41
- *
42
- * @copyright 2014 Daniel Zahariev
43
- * @copyright 2011 Dan Myers
44
- * @copyright 2008 Donovan Schonknecht
45
- */
46
 
47
  /**
48
- * SimpleEmailService PHP class
49
- *
50
- * @link https://github.com/daniel-zahariev/php-aws-ses
51
- * @package AmazonSimpleEmailService
52
- * @version v0.9.1
53
- */
54
  class SimpleEmailService
55
  {
56
- /**
57
- * @link(AWS SES regions, http://docs.aws.amazon.com/ses/latest/DeveloperGuide/regions.html)
58
- */
59
- const AWS_US_EAST_1 = 'email.us-east-1.amazonaws.com';
60
- const AWS_US_WEST_2 = 'email.us-west-2.amazonaws.com';
61
- const AWS_EU_WEST1 = 'email.eu-west-1.amazonaws.com';
62
-
63
- const REQUEST_SIGNATURE_V3 = 'v3';
64
- const REQUEST_SIGNATURE_V4 = 'v4';
65
-
66
- /**
67
- * AWS SES Target host of region
68
- */
69
- protected $__host;
70
-
71
- /**
72
- * AWS SES Access key
73
- */
74
- protected $__accessKey;
75
-
76
- /**
77
- * AWS Secret key
78
- */
79
- protected $__secretKey;
80
-
81
- /**
82
- * Enable/disable
83
- */
84
- protected $__trigger_errors;
85
-
86
- /**
87
- * Controls the reuse of CURL hander for sending a bulk of messages
88
- * @deprecated
89
- */
90
- protected $__bulk_sending_mode = false;
91
-
92
- /**
93
- * Optionally reusable SimpleEmailServiceRequest instance
94
- */
95
- protected $__ses_request = null;
96
-
97
- /**
98
- * Controls CURLOPT_SSL_VERIFYHOST setting for SimpleEmailServiceRequest's curl handler
99
- */
100
- protected $__verifyHost = true;
101
-
102
- /**
103
- * Controls CURLOPT_SSL_VERIFYPEER setting for SimpleEmailServiceRequest's curl handler
104
- */
105
- protected $__verifyPeer = true;
106
 
107
  /**
108
  * @var string HTTP Request signature version
109
  */
110
- protected $__requestSignatureVersion;
111
 
112
  /**
113
  * Constructor
@@ -118,14 +118,15 @@ class SimpleEmailService
118
  * @param boolean $trigger_errors Trigger PHP errors when AWS SES API returns an error
119
  * @param string $requestSignatureVersion Version of the request signature
120
  */
121
- public function __construct($accessKey = null, $secretKey = null, $host = self::AWS_US_EAST_1, $trigger_errors = true, $requestSignatureVersion = self::REQUEST_SIGNATURE_V4) {
122
- if ($accessKey !== null && $secretKey !== null) {
123
- $this->setAuth($accessKey, $secretKey);
124
- }
125
- $this->__host = $host;
126
- $this->__trigger_errors = $trigger_errors;
127
- $this->__requestSignatureVersion = $requestSignatureVersion;
128
- }
 
129
 
130
  /**
131
  * Set the request signature version
@@ -133,503 +134,546 @@ class SimpleEmailService
133
  * @param string $requestSignatureVersion
134
  * @return SimpleEmailService $this
135
  */
136
- public function setRequestSignatureVersion($requestSignatureVersion) {
137
- $this->__requestSignatureVersion = $requestSignatureVersion;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
- return $this;
140
  }
141
 
142
  /**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  * @return string
144
  */
145
- public function getRequestSignatureVersion() {
146
- return $this->__requestSignatureVersion;
 
 
 
 
 
 
 
 
 
 
147
  }
148
 
149
- /**
150
- * Set AWS access key and secret key
151
- *
152
- * @param string $accessKey Access key
153
- * @param string $secretKey Secret key
154
- * @return SimpleEmailService $this
155
- */
156
- public function setAuth($accessKey, $secretKey) {
157
- $this->__accessKey = $accessKey;
158
- $this->__secretKey = $secretKey;
159
-
160
- return $this;
161
- }
162
-
163
- /**
164
- * Set AWS Host
165
- * @param string $host AWS Host
166
- */
167
- public function setHost($host = self::AWS_US_EAST_1) {
168
- $this->__host = $host;
169
-
170
- return $this;
171
- }
172
-
173
- /**
174
- * @deprecated
175
- */
176
- public function enableVerifyHost($enable = true) {
177
- $this->__verifyHost = (bool)$enable;
178
-
179
- return $this;
180
- }
181
-
182
- /**
183
- * @deprecated
184
- */
185
- public function enableVerifyPeer($enable = true) {
186
- $this->__verifyPeer = (bool)$enable;
187
-
188
- return $this;
189
- }
190
-
191
- /**
192
- * @deprecated
193
- */
194
- public function verifyHost() {
195
- return $this->__verifyHost;
196
- }
197
-
198
- /**
199
- * @deprecated
200
- */
201
- public function verifyPeer() {
202
- return $this->__verifyPeer;
203
- }
204
-
205
-
206
- /**
207
- * Get AWS target host
208
- * @return boolean
209
- */
210
- public function getHost() {
211
- return $this->__host;
212
- }
213
-
214
- /**
215
- * Get AWS SES auth access key
216
- * @return string
217
- */
218
- public function getAccessKey() {
219
- return $this->__accessKey;
220
- }
221
-
222
- /**
223
- * Get AWS SES auth secret key
224
- * @return string
225
- */
226
- public function getSecretKey() {
227
- return $this->__secretKey;
228
- }
229
-
230
- /**
231
- * Get the verify peer CURL mode
232
- * @return boolean
233
- */
234
- public function getVerifyPeer() {
235
- return $this->__verifyPeer;
236
- }
237
-
238
- /**
239
- * Get the verify host CURL mode
240
- * @return boolean
241
- */
242
- public function getVerifyHost() {
243
- return $this->__verifyHost;
244
- }
245
-
246
- /**
247
- * Get bulk email sending mode
248
- * @deprecated
249
- * @return boolean
250
- */
251
- public function getBulkMode() {
252
- return $this->__bulk_sending_mode;
253
- }
254
-
255
-
256
- /**
257
- * Enable/disable CURLOPT_SSL_VERIFYHOST for SimpleEmailServiceRequest's curl handler
258
- * verifyHost and verifyPeer determine whether curl verifies ssl certificates.
259
- * It may be necessary to disable these checks on certain systems.
260
- * These only have an effect if SSL is enabled.
261
- *
262
- * @param boolean $enable New status for the mode
263
- * @return SimpleEmailService $this
264
- */
265
- public function setVerifyHost($enable = true) {
266
- $this->__verifyHost = (bool)$enable;
267
- return $this;
268
- }
269
-
270
- /**
271
- * Enable/disable CURLOPT_SSL_VERIFYPEER for SimpleEmailServiceRequest's curl handler
272
- * verifyHost and verifyPeer determine whether curl verifies ssl certificates.
273
- * It may be necessary to disable these checks on certain systems.
274
- * These only have an effect if SSL is enabled.
275
- *
276
- * @param boolean $enable New status for the mode
277
- * @return SimpleEmailService $this
278
- */
279
- public function setVerifyPeer($enable = true) {
280
- $this->__verifyPeer = (bool)$enable;
281
- return $this;
282
- }
283
-
284
- /**
285
- * Enable/disable bulk email sending mode
286
- *
287
- * @param boolean $enable New status for the mode
288
- * @return SimpleEmailService $this
289
- * @deprecated
290
- */
291
- public function setBulkMode($enable = true) {
292
- $this->__bulk_sending_mode = (bool)$enable;
293
- return $this;
294
- }
295
-
296
- /**
297
- * Lists the email addresses that have been verified and can be used as the 'From' address
298
- *
299
- * @return array An array containing two items: a list of verified email addresses, and the request id.
300
- */
301
- public function listVerifiedEmailAddresses() {
302
- $ses_request = $this->getRequestHandler('GET');
303
- $ses_request->setParameter('Action', 'ListVerifiedEmailAddresses');
304
-
305
- $ses_response = $ses_request->getResponse();
306
- if($ses_response->error === false && $ses_response->code !== 200) {
307
- $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
308
- }
309
- if($ses_response->error !== false) {
310
- $this->__triggerError('listVerifiedEmailAddresses', $ses_response->error);
311
- return false;
312
- }
313
-
314
- $response = array();
315
- if(!isset($ses_response->body)) {
316
- return $response;
317
- }
318
-
319
- $addresses = array();
320
- foreach($ses_response->body->ListVerifiedEmailAddressesResult->VerifiedEmailAddresses->member as $address) {
321
- $addresses[] = (string)$address;
322
- }
323
-
324
- $response['Addresses'] = $addresses;
325
- $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
326
-
327
- return $response;
328
- }
329
-
330
- /**
331
- * Requests verification of the provided email address, so it can be used
332
- * as the 'From' address when sending emails through SimpleEmailService.
333
- *
334
- * After submitting this request, you should receive a verification email
335
- * from Amazon at the specified address containing instructions to follow.
336
- *
337
- * @param string $email The email address to get verified
338
- * @return array The request id for this request.
339
- */
340
- public function verifyEmailAddress($email) {
341
- $ses_request = $this->getRequestHandler('POST');
342
- $ses_request->setParameter('Action', 'VerifyEmailAddress');
343
- $ses_request->setParameter('EmailAddress', $email);
344
-
345
- $ses_response = $ses_request->getResponse();
346
- if($ses_response->error === false && $ses_response->code !== 200) {
347
- $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
348
- }
349
- if($ses_response->error !== false) {
350
- $this->__triggerError('verifyEmailAddress', $ses_response->error);
351
- return false;
352
- }
353
-
354
- $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
355
- return $response;
356
- }
357
-
358
- /**
359
- * Removes the specified email address from the list of verified addresses.
360
- *
361
- * @param string $email The email address to remove
362
- * @return array The request id for this request.
363
- */
364
- public function deleteVerifiedEmailAddress($email) {
365
- $ses_request = $this->getRequestHandler('DELETE');
366
- $ses_request->setParameter('Action', 'DeleteVerifiedEmailAddress');
367
- $ses_request->setParameter('EmailAddress', $email);
368
-
369
- $ses_response = $ses_request->getResponse();
370
- if($ses_response->error === false && $ses_response->code !== 200) {
371
- $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
372
- }
373
- if($ses_response->error !== false) {
374
- $this->__triggerError('deleteVerifiedEmailAddress', $ses_response->error);
375
- return false;
376
- }
377
-
378
- $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
379
- return $response;
380
- }
381
-
382
- /**
383
- * Retrieves information on the current activity limits for this account.
384
- * See http://docs.amazonwebservices.com/ses/latest/APIReference/API_GetSendQuota.html
385
- *
386
- * @return array An array containing information on this account's activity limits.
387
- */
388
- public function getSendQuota() {
389
- $ses_request = $this->getRequestHandler('GET');
390
- $ses_request->setParameter('Action', 'GetSendQuota');
391
-
392
- $ses_response = $ses_request->getResponse();
393
- if($ses_response->error === false && $ses_response->code !== 200) {
394
- $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
395
- }
396
- if($ses_response->error !== false) {
397
- $this->__triggerError('getSendQuota', $ses_response->error);
398
- return false;
399
- }
400
-
401
- $response = array();
402
- if(!isset($ses_response->body)) {
403
- return $response;
404
- }
405
-
406
- $response['Max24HourSend'] = (string)$ses_response->body->GetSendQuotaResult->Max24HourSend;
407
- $response['MaxSendRate'] = (string)$ses_response->body->GetSendQuotaResult->MaxSendRate;
408
- $response['SentLast24Hours'] = (string)$ses_response->body->GetSendQuotaResult->SentLast24Hours;
409
- $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
410
-
411
- return $response;
412
- }
413
-
414
- /**
415
- * Retrieves statistics for the last two weeks of activity on this account.
416
- * See http://docs.amazonwebservices.com/ses/latest/APIReference/API_GetSendStatistics.html
417
- *
418
- * @return array An array of activity statistics. Each array item covers a 15-minute period.
419
- */
420
- public function getSendStatistics() {
421
- $ses_request = $this->getRequestHandler('GET');
422
- $ses_request->setParameter('Action', 'GetSendStatistics');
423
-
424
- $ses_response = $ses_request->getResponse();
425
- if($ses_response->error === false && $ses_response->code !== 200) {
426
- $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
427
- }
428
- if($ses_response->error !== false) {
429
- $this->__triggerError('getSendStatistics', $ses_response->error);
430
- return false;
431
- }
432
-
433
- $response = array();
434
- if(!isset($ses_response->body)) {
435
- return $response;
436
- }
437
-
438
- $datapoints = array();
439
- foreach($ses_response->body->GetSendStatisticsResult->SendDataPoints->member as $datapoint) {
440
- $p = array();
441
- $p['Bounces'] = (string)$datapoint->Bounces;
442
- $p['Complaints'] = (string)$datapoint->Complaints;
443
- $p['DeliveryAttempts'] = (string)$datapoint->DeliveryAttempts;
444
- $p['Rejects'] = (string)$datapoint->Rejects;
445
- $p['Timestamp'] = (string)$datapoint->Timestamp;
446
-
447
- $datapoints[] = $p;
448
- }
449
-
450
- $response['SendDataPoints'] = $datapoints;
451
- $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
452
-
453
- return $response;
454
- }
455
-
456
-
457
- /**
458
- * Given a SimpleEmailServiceMessage object, submits the message to the service for sending.
459
- *
460
- * @param SimpleEmailServiceMessage $sesMessage An instance of the message class
461
- * @param boolean $use_raw_request If this is true or there are attachments to the email `SendRawEmail` call will be used
462
- * @param boolean $trigger_error Optionally overwrite the class setting for triggering an error (with type check to true/false)
463
- * @return array An array containing the unique identifier for this message and a separate request id.
464
- * Returns false if the provided message is missing any required fields.
465
- * @link(AWS SES Response formats, http://docs.aws.amazon.com/ses/latest/DeveloperGuide/query-interface-responses.html)
466
- */
467
- public function sendEmail($sesMessage, $use_raw_request = false , $trigger_error = null) {
468
- if(!$sesMessage->validate()) {
469
- $this->__triggerError('sendEmail', 'Message failed validation.');
470
- return false;
471
- }
472
-
473
- $ses_request = $this->getRequestHandler('POST');
474
- $action = !empty($sesMessage->attachments) || $use_raw_request ? 'SendRawEmail' : 'SendEmail';
475
- $ses_request->setParameter('Action', $action);
476
-
477
- // Works with both calls
478
- if (!is_null($sesMessage->configuration_set)) {
479
- $ses_request->setParameter('ConfigurationSetName', $sesMessage->configuration_set);
480
- }
481
-
482
- if($action == 'SendRawEmail') {
483
- // https://docs.aws.amazon.com/ses/latest/APIReference/API_SendRawEmail.html
484
- $ses_request->setParameter('RawMessage.Data', $sesMessage->getRawMessage());
485
- } else {
486
- $i = 1;
487
- foreach($sesMessage->to as $to) {
488
- $ses_request->setParameter('Destination.ToAddresses.member.'.$i, $sesMessage->encodeRecipients($to));
489
- $i++;
490
- }
491
-
492
- if(is_array($sesMessage->cc)) {
493
- $i = 1;
494
- foreach($sesMessage->cc as $cc) {
495
- $ses_request->setParameter('Destination.CcAddresses.member.'.$i, $sesMessage->encodeRecipients($cc));
496
- $i++;
497
- }
498
- }
499
-
500
- if(is_array($sesMessage->bcc)) {
501
- $i = 1;
502
- foreach($sesMessage->bcc as $bcc) {
503
- $ses_request->setParameter('Destination.BccAddresses.member.'.$i, $sesMessage->encodeRecipients($bcc));
504
- $i++;
505
- }
506
- }
507
-
508
- if(is_array($sesMessage->replyto)) {
509
- $i = 1;
510
- foreach($sesMessage->replyto as $replyto) {
511
- $ses_request->setParameter('ReplyToAddresses.member.'.$i, $sesMessage->encodeRecipients($replyto));
512
- $i++;
513
- }
514
- }
515
-
516
- $ses_request->setParameter('Source', $sesMessage->encodeRecipients($sesMessage->from));
517
-
518
- if($sesMessage->returnpath != null) {
519
- $ses_request->setParameter('ReturnPath', $sesMessage->returnpath);
520
- }
521
-
522
- if($sesMessage->subject != null && strlen($sesMessage->subject) > 0) {
523
- $ses_request->setParameter('Message.Subject.Data', $sesMessage->subject);
524
- if($sesMessage->subjectCharset != null && strlen($sesMessage->subjectCharset) > 0) {
525
- $ses_request->setParameter('Message.Subject.Charset', $sesMessage->subjectCharset);
526
- }
527
- }
528
-
529
-
530
- if($sesMessage->messagetext != null && strlen($sesMessage->messagetext) > 0) {
531
- $ses_request->setParameter('Message.Body.Text.Data', $sesMessage->messagetext);
532
- if($sesMessage->messageTextCharset != null && strlen($sesMessage->messageTextCharset) > 0) {
533
- $ses_request->setParameter('Message.Body.Text.Charset', $sesMessage->messageTextCharset);
534
- }
535
- }
536
-
537
- if($sesMessage->messagehtml != null && strlen($sesMessage->messagehtml) > 0) {
538
- $ses_request->setParameter('Message.Body.Html.Data', $sesMessage->messagehtml);
539
- if($sesMessage->messageHtmlCharset != null && strlen($sesMessage->messageHtmlCharset) > 0) {
540
- $ses_request->setParameter('Message.Body.Html.Charset', $sesMessage->messageHtmlCharset);
541
- }
542
- }
543
-
544
- $i = 1;
545
- foreach($sesMessage->message_tags as $key => $value) {
546
- $ses_request->setParameter('Tags.member.'.$i.'.Name', $key);
547
- $ses_request->setParameter('Tags.member.'.$i.'.Value', $value);
548
- $i++;
549
- }
550
- }
551
-
552
- $ses_response = $ses_request->getResponse();
553
- if($ses_response->error === false && $ses_response->code !== 200) {
554
- $response = array(
555
- 'code' => $ses_response->code,
556
- 'error' => array('Error' => array('message' => 'Unexpected HTTP status')),
557
- );
558
- return $response;
559
- }
560
- if($ses_response->error !== false) {
561
- if (($this->__trigger_errors && ($trigger_error !== false)) || $trigger_error === true) {
562
- $this->__triggerError('sendEmail', $ses_response->error);
563
- return false;
564
- }
565
- return $ses_response;
566
- }
567
-
568
- $response = array(
569
- 'MessageId' => (string)$ses_response->body->{"{$action}Result"}->MessageId,
570
- 'RequestId' => (string)$ses_response->body->ResponseMetadata->RequestId,
571
- );
572
- return $response;
573
- }
574
-
575
- /**
576
- * Trigger an error message
577
- *
578
- * {@internal Used by member functions to output errors}
579
- * @param string $functionname The name of the function that failed
580
- * @param array $error Array containing error information
581
- * @return void
582
- */
583
- public function __triggerError($functionname, $error)
584
- {
585
- if($error == false)
586
- {
587
- trigger_error(sprintf("SimpleEmailService::%s(): Encountered an error, but no description given", $functionname), E_USER_WARNING);
588
- }
589
- else if(isset($error['curl']) && $error['curl'])
590
- {
591
- trigger_error(sprintf("SimpleEmailService::%s(): %s %s", $functionname, $error['code'], $error['message']), E_USER_WARNING);
592
- }
593
- else if(isset($error['Error']))
594
- {
595
- $e = $error['Error'];
596
- $message = sprintf("SimpleEmailService::%s(): %s - %s: %s\nRequest Id: %s\n", $functionname, $e['Type'], $e['Code'], $e['Message'], $error['RequestId']);
597
- trigger_error($message, E_USER_WARNING);
598
- }
599
- else {
600
- trigger_error(sprintf("SimpleEmailService::%s(): Encountered an error: %s", $functionname, $error), E_USER_WARNING);
601
- }
602
- }
603
-
604
- /**
605
- * Set SES Request
606
- *
607
- * @param SimpleEmailServiceRequest $ses_request description
608
- * @return SimpleEmailService $this
609
- */
610
- public function setRequestHandler(SimpleEmailServiceRequest $ses_request = null) {
611
- if (!is_null($ses_request)) {
612
- $ses_request->setSES($this);
613
- }
614
-
615
- $this->__ses_request = $ses_request;
616
-
617
- return $this;
618
- }
619
-
620
- /**
621
- * Get SES Request
622
- *
623
- * @param string $verb HTTP Verb: GET, POST, DELETE
624
- * @return SimpleEmailServiceRequest SES Request
625
- */
626
- public function getRequestHandler($verb) {
627
- if (empty($this->__ses_request)) {
628
- $this->__ses_request = new SimpleEmailServiceRequest($this, $verb);
629
- } else {
630
- $this->__ses_request->setVerb($verb);
631
- }
632
-
633
- return $this->__ses_request;
634
- }
635
  }
3
  namespace FluentMail\App\Services\Mailer\Providers\AmazonSes;
4
 
5
  /**
6
+ *
7
+ * Copyright (c) 2014, Daniel Zahariev.
8
+ * Copyright (c) 2011, Dan Myers.
9
+ * Parts copyright (c) 2008, Donovan Schonknecht.
10
+ * All rights reserved.
11
+ *
12
+ * Redistribution and use in source and binary forms, with or without
13
+ * modification, are permitted provided that the following conditions are met:
14
+ *
15
+ * - Redistributions of source code must retain the above copyright notice,
16
+ * this list of conditions and the following disclaimer.
17
+ * - Redistributions in binary form must reproduce the above copyright
18
+ * notice, this list of conditions and the following disclaimer in the
19
+ * documentation and/or other materials provided with the distribution.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
+ * POSSIBILITY OF SUCH DAMAGE.
32
+ *
33
+ * This is a modified BSD license (the third clause has been removed).
34
+ * The BSD license may be found here:
35
+ * http://www.opensource.org/licenses/bsd-license.php
36
+ *
37
+ * Amazon Simple Email Service is a trademark of Amazon.com, Inc. or its affiliates.
38
+ *
39
+ * SimpleEmailService is based on Donovan Schonknecht's Amazon S3 PHP class, found here:
40
+ * http://undesigned.org.za/2007/10/22/amazon-s3-php-class
41
+ *
42
+ * @copyright 2014 Daniel Zahariev
43
+ * @copyright 2011 Dan Myers
44
+ * @copyright 2008 Donovan Schonknecht
45
+ */
46
 
47
  /**
48
+ * SimpleEmailService PHP class
49
+ *
50
+ * @link https://github.com/daniel-zahariev/php-aws-ses
51
+ * @package AmazonSimpleEmailService
52
+ * @version v0.9.1
53
+ */
54
  class SimpleEmailService
55
  {
56
+ /**
57
+ * @link(AWS SES regions, http://docs.aws.amazon.com/ses/latest/DeveloperGuide/regions.html)
58
+ */
59
+ const AWS_US_EAST_1 = 'email.us-east-1.amazonaws.com';
60
+ const AWS_US_WEST_2 = 'email.us-west-2.amazonaws.com';
61
+ const AWS_EU_WEST1 = 'email.eu-west-1.amazonaws.com';
62
+
63
+ const REQUEST_SIGNATURE_V3 = 'v3';
64
+ const REQUEST_SIGNATURE_V4 = 'v4';
65
+
66
+ /**
67
+ * AWS SES Target host of region
68
+ */
69
+ protected $__host;
70
+
71
+ /**
72
+ * AWS SES Access key
73
+ */
74
+ protected $__accessKey;
75
+
76
+ /**
77
+ * AWS Secret key
78
+ */
79
+ protected $__secretKey;
80
+
81
+ /**
82
+ * Enable/disable
83
+ */
84
+ protected $__trigger_errors;
85
+
86
+ /**
87
+ * Controls the reuse of CURL hander for sending a bulk of messages
88
+ * @deprecated
89
+ */
90
+ protected $__bulk_sending_mode = false;
91
+
92
+ /**
93
+ * Optionally reusable SimpleEmailServiceRequest instance
94
+ */
95
+ protected $__ses_request = null;
96
+
97
+ /**
98
+ * Controls CURLOPT_SSL_VERIFYHOST setting for SimpleEmailServiceRequest's curl handler
99
+ */
100
+ protected $__verifyHost = true;
101
+
102
+ /**
103
+ * Controls CURLOPT_SSL_VERIFYPEER setting for SimpleEmailServiceRequest's curl handler
104
+ */
105
+ protected $__verifyPeer = true;
106
 
107
  /**
108
  * @var string HTTP Request signature version
109
  */
110
+ protected $__requestSignatureVersion;
111
 
112
  /**
113
  * Constructor
118
  * @param boolean $trigger_errors Trigger PHP errors when AWS SES API returns an error
119
  * @param string $requestSignatureVersion Version of the request signature
120
  */
121
+ public function __construct($accessKey = null, $secretKey = null, $host = self::AWS_US_EAST_1, $trigger_errors = true, $requestSignatureVersion = self::REQUEST_SIGNATURE_V4)
122
+ {
123
+ if ($accessKey !== null && $secretKey !== null) {
124
+ $this->setAuth($accessKey, $secretKey);
125
+ }
126
+ $this->__host = $host;
127
+ $this->__trigger_errors = $trigger_errors;
128
+ $this->__requestSignatureVersion = $requestSignatureVersion;
129
+ }
130
 
131
  /**
132
  * Set the request signature version
134
  * @param string $requestSignatureVersion
135
  * @return SimpleEmailService $this
136
  */
137
+ public function setRequestSignatureVersion($requestSignatureVersion)
138
+ {
139
+ $this->__requestSignatureVersion = $requestSignatureVersion;
140
+
141
+ return $this;
142
+ }
143
+
144
+ /**
145
+ * @return string
146
+ */
147
+ public function getRequestSignatureVersion()
148
+ {
149
+ return $this->__requestSignatureVersion;
150
+ }
151
+
152
+ /**
153
+ * Set AWS access key and secret key
154
+ *
155
+ * @param string $accessKey Access key
156
+ * @param string $secretKey Secret key
157
+ * @return SimpleEmailService $this
158
+ */
159
+ public function setAuth($accessKey, $secretKey)
160
+ {
161
+ $this->__accessKey = $accessKey;
162
+ $this->__secretKey = $secretKey;
163
+
164
+ return $this;
165
+ }
166
+
167
+ /**
168
+ * Set AWS Host
169
+ * @param string $host AWS Host
170
+ */
171
+ public function setHost($host = self::AWS_US_EAST_1)
172
+ {
173
+ $this->__host = $host;
174
+
175
+ return $this;
176
+ }
177
+
178
+ /**
179
+ * @deprecated
180
+ */
181
+ public function enableVerifyHost($enable = true)
182
+ {
183
+ $this->__verifyHost = (bool)$enable;
184
 
185
+ return $this;
186
  }
187
 
188
  /**
189
+ * @deprecated
190
+ */
191
+ public function enableVerifyPeer($enable = true)
192
+ {
193
+ $this->__verifyPeer = (bool)$enable;
194
+
195
+ return $this;
196
+ }
197
+
198
+ /**
199
+ * @deprecated
200
+ */
201
+ public function verifyHost()
202
+ {
203
+ return $this->__verifyHost;
204
+ }
205
+
206
+ /**
207
+ * @deprecated
208
+ */
209
+ public function verifyPeer()
210
+ {
211
+ return $this->__verifyPeer;
212
+ }
213
+
214
+
215
+ /**
216
+ * Get AWS target host
217
+ * @return boolean
218
+ */
219
+ public function getHost()
220
+ {
221
+ return $this->__host;
222
+ }
223
+
224
+ /**
225
+ * Get AWS SES auth access key
226
+ * @return string
227
+ */
228
+ public function getAccessKey()
229
+ {
230
+ return $this->__accessKey;
231
+ }
232
+
233
+ /**
234
+ * Get AWS SES auth secret key
235
  * @return string
236
  */
237
+ public function getSecretKey()
238
+ {
239
+ return $this->__secretKey;
240
+ }
241
+
242
+ /**
243
+ * Get the verify peer CURL mode
244
+ * @return boolean
245
+ */
246
+ public function getVerifyPeer()
247
+ {
248
+ return $this->__verifyPeer;
249
  }
250
 
251
+ /**
252
+ * Get the verify host CURL mode
253
+ * @return boolean
254
+ */
255
+ public function getVerifyHost()
256
+ {
257
+ return $this->__verifyHost;
258
+ }
259
+
260
+ /**
261
+ * Get bulk email sending mode
262
+ * @return boolean
263
+ * @deprecated
264
+ */
265
+ public function getBulkMode()
266
+ {
267
+ return $this->__bulk_sending_mode;
268
+ }
269
+
270
+
271
+ /**
272
+ * Enable/disable CURLOPT_SSL_VERIFYHOST for SimpleEmailServiceRequest's curl handler
273
+ * verifyHost and verifyPeer determine whether curl verifies ssl certificates.
274
+ * It may be necessary to disable these checks on certain systems.
275
+ * These only have an effect if SSL is enabled.
276
+ *
277
+ * @param boolean $enable New status for the mode
278
+ * @return SimpleEmailService $this
279
+ */
280
+ public function setVerifyHost($enable = true)
281
+ {
282
+ $this->__verifyHost = (bool)$enable;
283
+ return $this;
284
+ }
285
+
286
+ /**
287
+ * Enable/disable CURLOPT_SSL_VERIFYPEER for SimpleEmailServiceRequest's curl handler
288
+ * verifyHost and verifyPeer determine whether curl verifies ssl certificates.
289
+ * It may be necessary to disable these checks on certain systems.
290
+ * These only have an effect if SSL is enabled.
291
+ *
292
+ * @param boolean $enable New status for the mode
293
+ * @return SimpleEmailService $this
294
+ */
295
+ public function setVerifyPeer($enable = true)
296
+ {
297
+ $this->__verifyPeer = (bool)$enable;
298
+ return $this;
299
+ }
300
+
301
+ /**
302
+ * Enable/disable bulk email sending mode
303
+ *
304
+ * @param boolean $enable New status for the mode
305
+ * @return SimpleEmailService $this
306
+ * @deprecated
307
+ */
308
+ public function setBulkMode($enable = true)
309
+ {
310
+ $this->__bulk_sending_mode = (bool)$enable;
311
+ return $this;
312
+ }
313
+
314
+ /**
315
+ * Lists the email addresses that have been verified and can be used as the 'From' address
316
+ *
317
+ * @return array An array containing two items: a list of verified email addresses, and the request id.
318
+ */
319
+ public function listVerifiedEmailAddresses()
320
+ {
321
+ $ses_request = $this->getRequestHandler('GET');
322
+ $ses_request->setParameter('Action', 'ListVerifiedEmailAddresses');
323
+
324
+ $ses_response = $ses_request->getResponse();
325
+ if ($ses_response->error === false && $ses_response->code !== 200) {
326
+ $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
327
+ }
328
+ if ($ses_response->error !== false) {
329
+ $this->__triggerError('listVerifiedEmailAddresses', $ses_response->error);
330
+ return false;
331
+ }
332
+
333
+ $response = array();
334
+ if (!isset($ses_response->body)) {
335
+ return $response;
336
+ }
337
+
338
+ $addresses = array();
339
+ foreach ($ses_response->body->ListVerifiedEmailAddressesResult->VerifiedEmailAddresses->member as $address) {
340
+ $addresses[] = (string)$address;
341
+ }
342
+
343
+ $response['Addresses'] = $addresses;
344
+ $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
345
+
346
+ return $response;
347
+ }
348
+
349
+ /**
350
+ * Requests verification of the provided email address, so it can be used
351
+ * as the 'From' address when sending emails through SimpleEmailService.
352
+ *
353
+ * After submitting this request, you should receive a verification email
354
+ * from Amazon at the specified address containing instructions to follow.
355
+ *
356
+ * @param string $email The email address to get verified
357
+ * @return array The request id for this request.
358
+ */
359
+ public function verifyEmailAddress($email)
360
+ {
361
+ $ses_request = $this->getRequestHandler('POST');
362
+ $ses_request->setParameter('Action', 'VerifyEmailAddress');
363
+ $ses_request->setParameter('EmailAddress', $email);
364
+
365
+ $ses_response = $ses_request->getResponse();
366
+ if ($ses_response->error === false && $ses_response->code !== 200) {
367
+ $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
368
+ }
369
+ if ($ses_response->error !== false) {
370
+ $this->__triggerError('verifyEmailAddress', $ses_response->error);
371
+ return false;
372
+ }
373
+
374
+ $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
375
+ return $response;
376
+ }
377
+
378
+ /**
379
+ * Removes the specified email address from the list of verified addresses.
380
+ *
381
+ * @param string $email The email address to remove
382
+ * @return array The request id for this request.
383
+ */
384
+ public function deleteVerifiedEmailAddress($email)
385
+ {
386
+ $ses_request = $this->getRequestHandler('DELETE');
387
+ $ses_request->setParameter('Action', 'DeleteVerifiedEmailAddress');
388
+ $ses_request->setParameter('EmailAddress', $email);
389
+
390
+ $ses_response = $ses_request->getResponse();
391
+ if ($ses_response->error === false && $ses_response->code !== 200) {
392
+ $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
393
+ }
394
+ if ($ses_response->error !== false) {
395
+ $this->__triggerError('deleteVerifiedEmailAddress', $ses_response->error);
396
+ return false;
397
+ }
398
+
399
+ $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
400
+ return $response;
401
+ }
402
+
403
+ /**
404
+ * Retrieves information on the current activity limits for this account.
405
+ * See http://docs.amazonwebservices.com/ses/latest/APIReference/API_GetSendQuota.html
406
+ *
407
+ * @return array An array containing information on this account's activity limits.
408
+ */
409
+ public function getSendQuota()
410
+ {
411
+ $ses_request = $this->getRequestHandler('GET');
412
+ $ses_request->setParameter('Action', 'GetSendQuota');
413
+
414
+ $ses_response = $ses_request->getResponse();
415
+ if ($ses_response->error === false && $ses_response->code !== 200) {
416
+ $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
417
+ }
418
+ if ($ses_response->error !== false) {
419
+ $this->__triggerError('getSendQuota', $ses_response->error);
420
+ return false;
421
+ }
422
+
423
+ $response = array();
424
+ if (!isset($ses_response->body)) {
425
+ return $response;
426
+ }
427
+
428
+ $response['Max24HourSend'] = (string)$ses_response->body->GetSendQuotaResult->Max24HourSend;
429
+ $response['MaxSendRate'] = (string)$ses_response->body->GetSendQuotaResult->MaxSendRate;
430
+ $response['SentLast24Hours'] = (string)$ses_response->body->GetSendQuotaResult->SentLast24Hours;
431
+ $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
432
+
433
+ return $response;
434
+ }
435
+
436
+ /**
437
+ * Retrieves statistics for the last two weeks of activity on this account.
438
+ * See http://docs.amazonwebservices.com/ses/latest/APIReference/API_GetSendStatistics.html
439
+ *
440
+ * @return array An array of activity statistics. Each array item covers a 15-minute period.
441
+ */
442
+ public function getSendStatistics()
443
+ {
444
+ $ses_request = $this->getRequestHandler('GET');
445
+ $ses_request->setParameter('Action', 'GetSendStatistics');
446
+
447
+ $ses_response = $ses_request->getResponse();
448
+ if ($ses_response->error === false && $ses_response->code !== 200) {
449
+ $ses_response->error = array('code' => $ses_response->code, 'message' => 'Unexpected HTTP status');
450
+ }
451
+ if ($ses_response->error !== false) {
452
+ $this->__triggerError('getSendStatistics', $ses_response->error);
453
+ return false;
454
+ }
455
+
456
+ $response = array();
457
+ if (!isset($ses_response->body)) {
458
+ return $response;
459
+ }
460
+
461
+ $datapoints = array();
462
+ foreach ($ses_response->body->GetSendStatisticsResult->SendDataPoints->member as $datapoint) {
463
+ $p = array();
464
+ $p['Bounces'] = (string)$datapoint->Bounces;
465
+ $p['Complaints'] = (string)$datapoint->Complaints;
466
+ $p['DeliveryAttempts'] = (string)$datapoint->DeliveryAttempts;
467
+ $p['Rejects'] = (string)$datapoint->Rejects;
468
+ $p['Timestamp'] = (string)$datapoint->Timestamp;
469
+
470
+ $datapoints[] = $p;
471
+ }
472
+
473
+ $response['SendDataPoints'] = $datapoints;
474
+ $response['RequestId'] = (string)$ses_response->body->ResponseMetadata->RequestId;
475
+
476
+ return $response;
477
+ }
478
+
479
+
480
+ /**
481
+ * Given a SimpleEmailServiceMessage object, submits the message to the service for sending.
482
+ *
483
+ * @param SimpleEmailServiceMessage $sesMessage An instance of the message class
484
+ * @param boolean $use_raw_request If this is true or there are attachments to the email `SendRawEmail` call will be used
485
+ * @param boolean $trigger_error Optionally overwrite the class setting for triggering an error (with type check to true/false)
486
+ * @return array An array containing the unique identifier for this message and a separate request id.
487
+ * Returns false if the provided message is missing any required fields.
488
+ * @link(AWS SES Response formats, http://docs.aws.amazon.com/ses/latest/DeveloperGuide/query-interface-responses.html)
489
+ */
490
+ public function sendEmail($sesMessage, $use_raw_request = false, $trigger_error = null)
491
+ {
492
+ if (!$sesMessage->validate()) {
493
+ $this->__triggerError('sendEmail', 'Message failed validation.');
494
+ return false;
495
+ }
496
+
497
+ $ses_request = $this->getRequestHandler('POST');
498
+ $action = !empty($sesMessage->attachments) || $use_raw_request ? 'SendRawEmail' : 'SendEmail';
499
+ $ses_request->setParameter('Action', $action);
500
+
501
+ // Works with both calls
502
+ if (!is_null($sesMessage->configuration_set)) {
503
+ $ses_request->setParameter('ConfigurationSetName', $sesMessage->configuration_set);
504
+ }
505
+
506
+ if ($action == 'SendRawEmail') {
507
+ // https://docs.aws.amazon.com/ses/latest/APIReference/API_SendRawEmail.html
508
+ $ses_request->setParameter('RawMessage.Data', $sesMessage->mime);
509
+ } else {
510
+ $i = 1;
511
+ foreach ($sesMessage->to as $to) {
512
+ $ses_request->setParameter('Destination.ToAddresses.member.' . $i, $sesMessage->encodeRecipients($to));
513
+ $i++;
514
+ }
515
+
516
+ if (is_array($sesMessage->cc)) {
517
+ $i = 1;
518
+ foreach ($sesMessage->cc as $cc) {
519
+ $ses_request->setParameter('Destination.CcAddresses.member.' . $i, $sesMessage->encodeRecipients($cc));
520
+ $i++;
521
+ }
522
+ }
523
+
524
+ if (is_array($sesMessage->bcc)) {
525
+ $i = 1;
526
+ foreach ($sesMessage->bcc as $bcc) {
527
+ $ses_request->setParameter('Destination.BccAddresses.member.' . $i, $sesMessage->encodeRecipients($bcc));
528
+ $i++;
529
+ }
530
+ }
531
+
532
+ if (is_array($sesMessage->replyto)) {
533
+ $i = 1;
534
+ foreach ($sesMessage->replyto as $replyto) {
535
+ $ses_request->setParameter('ReplyToAddresses.member.' . $i, $sesMessage->encodeRecipients($replyto));
536
+ $i++;
537
+ }
538
+ }
539
+
540
+ $ses_request->setParameter('Source', $sesMessage->encodeRecipients($sesMessage->from));
541
+
542
+ if ($sesMessage->returnpath != null) {
543
+ $ses_request->setParameter('ReturnPath', $sesMessage->returnpath);
544
+ }
545
+
546
+ if ($sesMessage->subject != null && strlen($sesMessage->subject) > 0) {
547
+ $ses_request->setParameter('Message.Subject.Data', $sesMessage->subject);
548
+ if ($sesMessage->subjectCharset != null && strlen($sesMessage->subjectCharset) > 0) {
549
+ $ses_request->setParameter('Message.Subject.Charset', $sesMessage->subjectCharset);
550
+ }
551
+ }
552
+
553
+
554
+ if ($sesMessage->messagetext != null && strlen($sesMessage->messagetext) > 0) {
555
+ $ses_request->setParameter('Message.Body.Text.Data', $sesMessage->messagetext);
556
+ if ($sesMessage->messageTextCharset != null && strlen($sesMessage->messageTextCharset) > 0) {
557
+ $ses_request->setParameter('Message.Body.Text.Charset', $sesMessage->messageTextCharset);
558
+ }
559
+ }
560
+
561
+ if ($sesMessage->messagehtml != null && strlen($sesMessage->messagehtml) > 0) {
562
+ $ses_request->setParameter('Message.Body.Html.Data', $sesMessage->messagehtml);
563
+ if ($sesMessage->messageHtmlCharset != null && strlen($sesMessage->messageHtmlCharset) > 0) {
564
+ $ses_request->setParameter('Message.Body.Html.Charset', $sesMessage->messageHtmlCharset);
565
+ }
566
+ }
567
+
568
+ $i = 1;
569
+ foreach ($sesMessage->message_tags as $key => $value) {
570
+ $ses_request->setParameter('Tags.member.' . $i . '.Name', $key);
571
+ $ses_request->setParameter('Tags.member.' . $i . '.Value', $value);
572
+ $i++;
573
+ }
574
+ }
575
+
576
+ $ses_response = $ses_request->getResponse();
577
+ if ($ses_response->error === false && $ses_response->code !== 200) {
578
+ $response = array(
579
+ 'code' => $ses_response->code,
580
+ 'error' => array('Error' => array('message' => 'Unexpected HTTP status')),
581
+ );
582
+ return $response;
583
+ }
584
+ if ($ses_response->error !== false) {
585
+ if (($this->__trigger_errors && ($trigger_error !== false)) || $trigger_error === true) {
586
+ $this->__triggerError('sendEmail', $ses_response->error);
587
+ return false;
588
+ }
589
+ return $ses_response;
590
+ }
591
+
592
+ $response = array(
593
+ 'MessageId' => (string)$ses_response->body->{"{$action}Result"}->MessageId,
594
+ 'RequestId' => (string)$ses_response->body->ResponseMetadata->RequestId,
595
+ );
596
+ return $response;
597
+ }
598
+
599
+
600
+ public function sendRawEmail($sesMessage)
601
+ {
602
+ $ses_request = $this->getRequestHandler('POST');
603
+ $ses_request->setParameter('Action', 'SendRawEmail');
604
+
605
+ // https://docs.aws.amazon.com/ses/latest/APIReference/API_SendRawEmail.html
606
+ $ses_request->setParameter('RawMessage.Data', $sesMessage);
607
+
608
+ $ses_response = $ses_request->getResponse();
609
+ if (($ses_response->error === false && $ses_response->code !== 200) || $ses_response->error !== false) {
610
+ return new \WP_Error($ses_response->code, $this->getErrorMessage('sendRawEmail', $ses_response->error), $ses_response->error);
611
+ }
612
+
613
+ return array(
614
+ 'MessageId' => (string)$ses_response->body->SendRawEmailResult->MessageId,
615
+ 'RequestId' => (string)$ses_response->body->ResponseMetadata->RequestId,
616
+ );
617
+ }
618
+
619
+ /**
620
+ * Trigger an error message
621
+ *
622
+ * {@internal Used by member functions to output errors}
623
+ * @param string $functionname The name of the function that failed
624
+ * @param array $error Array containing error information
625
+ * @return void
626
+ */
627
+ public function __triggerError($functionname, $error)
628
+ {
629
+ trigger_error($this->getErrorMessage($functionname, $error), E_USER_WARNING);
630
+ }
631
+
632
+ public function getErrorMessage($functionname, $error)
633
+ {
634
+ if ($error == false) {
635
+ return sprintf("SimpleEmailService::%s(): Encountered an error, but no description given", $functionname);
636
+ } else if (isset($error['curl']) && $error['curl']) {
637
+ return sprintf("SimpleEmailService::%s(): %s %s", $functionname, $error['code'], $error['message']);
638
+ } else if (isset($error['Error'])) {
639
+ $e = $error['Error'];
640
+ return sprintf("SimpleEmailService::%s(): %s - %s: %s\nRequest Id: %s\n", $functionname, $e['Type'], $e['Code'], $e['Message'], $error['RequestId']);
641
+ }
642
+
643
+ return sprintf("SimpleEmailService::%s(): Encountered an error: %s", $functionname, $error);
644
+ }
645
+
646
+ /**
647
+ * Set SES Request
648
+ *
649
+ * @param SimpleEmailServiceRequest $ses_request description
650
+ * @return SimpleEmailService $this
651
+ */
652
+ public function setRequestHandler(SimpleEmailServiceRequest $ses_request = null)
653
+ {
654
+ if (!is_null($ses_request)) {
655
+ $ses_request->setSES($this);
656
+ }
657
+
658
+ $this->__ses_request = $ses_request;
659
+
660
+ return $this;
661
+ }
662
+
663
+ /**
664
+ * Get SES Request
665
+ *
666
+ * @param string $verb HTTP Verb: GET, POST, DELETE
667
+ * @return SimpleEmailServiceRequest SES Request
668
+ */
669
+ public function getRequestHandler($verb)
670
+ {
671
+ if (empty($this->__ses_request)) {
672
+ $this->__ses_request = new SimpleEmailServiceRequest($this, $verb);
673
+ } else {
674
+ $this->__ses_request->setVerb($verb);
675
+ }
676
+
677
+ return $this->__ses_request;
678
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
679
  }
app/Services/Mailer/Providers/AmazonSes/SimpleEmailServiceMessage.php CHANGED
@@ -19,6 +19,7 @@ final class SimpleEmailServiceMessage {
19
  public $subjectCharset, $messageTextCharset, $messageHtmlCharset;
20
  public $attachments, $customHeaders, $configuration_set, $message_tags;
21
  public $is_clean, $raw_message;
 
22
 
23
  public function __construct() {
24
  $this->to = array();
@@ -551,6 +552,7 @@ final class SimpleEmailServiceMessage {
551
  $raw_message .= $this->messagetext . "\n";
552
  }
553
 
 
554
  if ($this->messagehtml != null && strlen($this->messagehtml) > 0) {
555
  $charset = empty($this->messageHtmlCharset) ? '' : "; charset=\"{$this->messageHtmlCharset}\"";
556
  $raw_message .= "\n--alt-{$boundary}\n";
19
  public $subjectCharset, $messageTextCharset, $messageHtmlCharset;
20
  public $attachments, $customHeaders, $configuration_set, $message_tags;
21
  public $is_clean, $raw_message;
22