File Coverage

blib/lib/Email/SendGrid/V3.pm
Criterion Covered Total %
statement 76 251 30.2
branch 24 144 16.6
condition 5 42 11.9
subroutine 15 47 31.9
pod 37 37 100.0
total 157 521 30.1


line stmt bran cond sub pod time code
1             package Email::SendGrid::V3;
2              
3             our $AUTHORITY = 'cpan:GSG';
4             our $VERSION = '0.90';
5              
6 1     1   189357 use v5.10.1;
  1         3  
7 1     1   4 use strict;
  1         1  
  1         16  
8 1     1   3 use warnings;
  1         1  
  1         17  
9              
10 1     1   4 use Carp;
  1         1  
  1         35  
11 1     1   489 use JSON;
  1         7381  
  1         5  
12 1     1   758 use HTTP::Tiny;
  1         32458  
  1         38  
13              
14 1     1   6 use constant DEFAULT_ENDPOINT => 'https://api.sendgrid.com/v3/mail/send';
  1         2  
  1         68  
15              
16 1     1   370 use namespace::clean; # don't export the above
  1         11527  
  1         4  
17              
18             =encoding utf8
19              
20             =head1 NAME
21              
22             Email::SendGrid::V3 - Class for building a message to be sent through the SendGrid v3 Web API
23              
24             =head1 VERSION
25              
26             version 0.90
27              
28             =head1 SYNOPSIS
29              
30             use Email::SendGrid::V3;
31              
32             my $sg = Email::SendGrid::V3->new(api_key => 'XYZ123');
33              
34             my $result = $sg->from('nobody@example.com')
35             ->subject('A test message for you')
36             ->add_content('text/plain', 'This is a test message sent with SendGrid')
37             ->add_envelope( to => [ 'nobody@example.com' ] )
38             ->send;
39              
40             print $result->{success} ? "It worked" : "It failed: " . $result->{reason};
41              
42             =head1 DESCRIPTION
43              
44             This module allows for easy integration with the SendGrid email distribution
45             service and its v3 Web API. All instance methods are chainable.
46              
47             For the full details of the SendGrid v3 API, see L
48              
49             =head1 CLASS METHODS
50              
51             =head2 Creation
52              
53             =head3 new(%args)
54              
55             Creates a new Email::SendGrid object. Optional param: 'api_key'
56              
57             =cut
58              
59             sub new {
60 1     1 1 4923 my ($class, %args) = @_;
61 1   33     5 $class = ref($class) || $class;
62              
63 1         4 my $self = bless +{
64             %args,
65             data => {},
66             }, $class;
67              
68 1         3 return $self;
69             }
70              
71             =head1 INSTANCE METHODS
72              
73             =head2 Sending / Validating
74              
75             =head3 send(%args)
76              
77             Sends the API request and returns a result hashref with these keys:
78              
79             =over 4
80              
81             =item *
82              
83             C - Boolean indicating whether the operation returned a 2XX status code
84              
85             =item *
86              
87             C - The HTTP status code of the response
88              
89             =item *
90              
91             C - The response phrase returned by the server
92              
93             =item *
94              
95             C - The body of the response, including a detailed error message, if any.
96              
97             =back
98              
99             =cut
100              
101             sub send {
102 0     0 1 0 my ($self, %args) = @_;
103 0 0 0     0 my $api_key = $args{api_key} || $self->{api_key} or croak "API key is required to send";
104 0   0     0 my $endpoint = $args{endpoint} || $self->{endpoint} || DEFAULT_ENDPOINT;
105 0         0 my $payload = $self->_payload;
106              
107 0         0 my $http = HTTP::Tiny->new(
108             keep_alive => 0,
109             default_headers => {
110             'Content-Type' => 'application/json',
111             'Authorization' => "Bearer $api_key",
112             },
113             );
114              
115 0         0 my $response = $http->post(
116             $endpoint, { content => $payload },
117             );
118              
119 0         0 return $response;
120             }
121              
122             =head3 validate(%args)
123              
124             Temporarily sets the 'sandbox_mode' flag to true, and submits the API request
125             to SendGrid. Returns the same hashref format as send(). If the 'success' key
126             is true, the API request is valid.
127              
128             =cut
129              
130             sub validate {
131 0     0 1 0 my ($self, %args) = @_;
132              
133 0         0 local $self->{data}{mail_settings}{sandbox_mode} = { enable => JSON::true };
134              
135 0         0 return $self->send(%args);
136             }
137              
138             sub _payload {
139 2     2   49 my ($self) = @_;
140 2         30 return JSON->new->canonical->encode( $self->{data} );
141             }
142              
143             =head2 Personalizations / Envelopes
144              
145             =head3 $self->add_envelope(%args);
146              
147             Once you've defined the general message parameters (by setting from, content, etc)
148             You must add at least one envelope. Each envelope represents one personalized copy
149             of a message, and who should receive it. Some parameters can only be set at the message
150             level, some only at the envelope level, and some at both (the envelop-level settings will
151             override the message-level settings).
152              
153             You must specify at least the 'to' argument, which is an array of recipient emails. This
154             can be a plain array of addresses, or an array of hashes with 'email' and 'name' keys.
155              
156             The 'cc' and 'bcc' arguments are optional, but follow the same format of the 'to' argument.
157              
158             In addition to specifying the envelope recipients via to/cc/bcc, you can also override the
159             message 'subject', 'send_at', 'headers' hash, 'substitutions' hash, and 'custom_args' hash.
160             See the message-level methods for more details on those parameters.
161              
162             =cut
163              
164             sub add_envelope {
165 4     4 1 11 my ($self, %args) = @_;
166              
167 4         9 my $to = _standardize_recips('to', $args{to});
168 4         15 my $cc = _standardize_recips('cc', $args{cc});
169 4         10 my $bcc = _standardize_recips('bcc', $args{bcc});
170              
171 4 50       7 croak "Envelope must include at least one 'to' address" unless @$to;
172              
173 4         8 my $envelope = { to => $to };
174 4 50       5 $envelope->{cc} = $cc if @$cc;
175 4 50       6 $envelope->{bcc} = $bcc if @$bcc;
176              
177 4 50       7 $envelope->{subject} = $args{subject} if $args{subject};
178 4 50       5 $envelope->{send_at} = $args{send_at} if $args{send_at};
179              
180 4 50       6 if ($args{headers}) {
181 0 0       0 croak "Envelope headers must be a hashref" unless ref $args{headers} eq 'HASH';
182 0         0 $envelope->{headers} = $args{headers};
183             }
184              
185 4 50       6 if ($args{substitutions}) {
186 0 0       0 croak "Envelope substitutions must be a hashref" unless ref $args{substitutions} eq 'HASH';
187 0         0 $envelope->{substitutions} = $args{substitutions};
188             }
189              
190 4 50       6 if ($args{dynamic_template_data}) {
191 0 0       0 croak "Envelope dynamic_template_data must be a hashref" unless ref $args{dynamic_template_data} eq 'HASH';
192 0         0 $envelope->{dynamic_template_data} = $args{dynamic_template_data};
193             }
194              
195 4 50       6 if ($args{custom_args}) {
196 0 0       0 croak "Envelope custom args must be a hashref" unless ref $args{custom_args} eq 'HASH';
197 0         0 $envelope->{custom_args} = $args{custom_args};
198             }
199              
200 4   100     14 $self->{data}{personalizations} ||= [];
201              
202 4         26 push @{ $self->{data}{personalizations} }, $envelope;
  4         8  
203              
204 4         9 return $self;
205             }
206              
207             sub _standardize_recips {
208 12     12   20 my ($name, $data) = @_;
209 12         16 my $reftype = ref $data;
210              
211 12 100       20 return [] unless $data;
212              
213 4 100       13 if (! $reftype) {
    100          
    50          
214 1         2 $data = [$data];
215             }
216             elsif ($reftype eq 'HASH') {
217 1         1 $data = [$data];
218             }
219             elsif ($reftype ne 'ARRAY') {
220 0         0 croak "Envelope $name must be an array";
221             }
222              
223 4         5 my @return;
224 4         6 foreach my $recip (@$data) {
225 5 50       7 next unless $recip;
226              
227 5         6 my $recipreftype = ref $recip;
228              
229 5 100       9 if (! $recipreftype) {
    50          
230 3         8 push @return, {
231             email => $recip,
232             };
233             }
234             elsif ($recipreftype eq 'HASH') {
235 2         4 push @return, $recip;
236             }
237             else {
238 0         0 croak "Invalid envelope $name";
239             }
240             }
241              
242 4         6 return \@return;
243             }
244              
245             =head3 $self->clear_envelopes();
246              
247             Clears all of the currently defined envelopes from this message.
248              
249             =cut
250              
251             sub clear_envelopes {
252 0     0 1 0 my ($self) = @_;
253              
254 0         0 delete $self->{data}{personalizations};
255              
256 0         0 return $self;
257             }
258              
259             =head2 Messages
260              
261             =head3 $self->from($email, $name);
262              
263             Sets the name/email address of the sender.
264             Email is required, name is optional.
265              
266             =cut
267              
268             sub from {
269 1     1 1 5 my ($self, $email, $name) = @_;
270              
271 1 50       2 croak "From email is required" unless $email;
272              
273 1         5 $self->{data}{from} = { email => $email };
274 1 50       3 $self->{data}{from}{name} = $name if $name;
275              
276 1         3 return $self;
277             }
278              
279             =head3 $self->subject($subject);
280              
281             Sets the subject of the message.
282             Required, but can be overridden at the message personalization level.
283              
284             =cut
285              
286             sub subject {
287 1     1 1 3 my ($self, $subject) = @_;
288              
289 1 50       2 croak "Subject is required" unless $subject;
290              
291 1         2 $self->{data}{subject} = $subject;
292              
293 1         4 return $self;
294             }
295              
296             =head3 $self->reply_to($email, $name);
297              
298             Sets the target that will be used if the recipient wants to reply to this message.
299             Email is required, name is optional.
300              
301             =cut
302              
303             sub reply_to {
304 0     0 1 0 my ($self, $email, $name) = @_;
305              
306 0 0       0 croak "Reply-to email is required" unless $email;
307              
308 0         0 $self->{data}{reply_to} = { email => $email };
309 0 0       0 $self->{data}{reply_to}{name} = $name if $name;
310              
311 0         0 return $self;
312             }
313              
314             =head3 $self->clear_content();
315              
316             Clears out all of the message body parts.
317              
318             =cut
319              
320             sub clear_content {
321 0     0 1 0 my ($self) = @_;
322              
323 0         0 delete $self->{data}{content};
324              
325 0         0 return $self;
326             }
327              
328             =head3 $self->add_content($type, $value);
329              
330             Adds a message body part. Both type and value are required.
331             $type should be something like "text/plain" or "text/html".
332              
333             =cut
334              
335             sub add_content {
336 1     1 1 2 my ($self, $type, $value) = @_;
337              
338 1 50 33     5 croak "Content type and value are required" unless $type && $value;
339              
340 1   50     13 $self->{data}{content} ||= [];
341              
342 1         2 push @{ $self->{data}{content} }, {
  1         14  
343             type => $type,
344             value => $value,
345             };
346              
347 1         5 return $self;
348             }
349              
350             =head3 $self->clear_attachments();
351              
352             Removes all attachments from this message.
353              
354             =cut
355              
356             sub clear_attachments {
357 0     0 1   my ($self) = @_;
358              
359 0           delete $self->{data}{attachments};
360              
361 0           return $self;
362             }
363              
364             =head3 $self->add_attachment($filename, $content, %args);
365              
366             Adds a new attachment to this message. $filename specifies the file name the recipient will see.
367             $content should be the Base64-encoded data of the file. Optional arguments are 'type' (the mime type
368             of the file, such as "image/jpeg"), 'disposition' must be "inline" or "attachment", and 'content_id'
369             which is used to identify embedded inline attachments.
370              
371             =cut
372              
373             sub add_attachment {
374 0     0 1   my ($self, $filename, $content, %args) = @_;
375              
376 0 0 0       croak "Attachment filename and content are required" unless $filename && $content;
377              
378 0           my $new_attachment = {
379             filename => $filename,
380             content => $content,
381             };
382              
383 0 0         $new_attachment->{type} = $args{type} if $args{type};
384 0 0         $new_attachment->{disposition} = $args{disposition} if $args{disposition};
385 0 0         $new_attachment->{content_id} = $args{content_id} if $args{content_id};
386              
387 0   0       $self->{data}{attachments} ||= [];
388 0           push @{ $self->{data}{attachments} }, $new_attachment;
  0            
389              
390 0           return $self;
391             }
392              
393             =head3 $self->template_id($template_id);
394              
395             Specifies the template you'd like to use for this message. Templates are managed via the
396             SendGrid application website. If the template includes a subject or body, those do not need
397             to be specified via this api.
398              
399             =cut
400              
401             sub template_id {
402 0     0 1   my ($self, $template_id) = @_;
403              
404 0           delete $self->{data}{template_id};
405 0 0         $self->{data}{template_id} = $template_id if $template_id;
406              
407 0           return $self;
408             }
409              
410             =head3 $self->clear_sections();
411              
412             Clears all substitution sections defined in this message.
413              
414             =cut
415              
416             sub clear_sections {
417 0     0 1   my ($self) = @_;
418              
419 0           delete $self->{data}{sections};
420              
421 0           return $self;
422             }
423              
424             =head3 $self->remove_section($key);
425              
426             Removes one substitution section defined in this message.
427              
428             =cut
429              
430             sub remove_section {
431 0     0 1   my ($self, $key) = @_;
432              
433 0 0         croak "Section key name is required" unless $key;
434              
435 0           delete $self->{data}{sections}{$key};
436              
437 0           return $self;
438             }
439              
440             =head3 $self->set_section($key, $value);
441              
442             Sets one new substitution section for this message. Each occurrence of $key
443             in each body part will be replaced with $value prior to personalization
444             substitutions (if any).
445              
446             =cut
447              
448             sub set_section {
449 0     0 1   my ($self, $key, $value) = @_;
450              
451 0 0         croak "Section key name is required" unless $key;
452              
453 0   0       $self->{data}{sections} ||= {};
454 0           $self->{data}{sections}{$key} = $value;
455              
456 0           return $self;
457             }
458              
459             =head3 $self->set_sections(%sections);
460              
461             Sets all substitution sections for this message at once. For each key/val pair,
462             occurrences of the key in the message body will be replaced by the value prior to
463             personalization substitutions (if any).
464              
465             =cut
466              
467             sub set_sections {
468 0     0 1   my ($self, %sections) = @_;
469              
470 0           delete $self->{data}{sections};
471 0 0         $self->{data}{sections} = \%sections if %sections;
472              
473 0           return $self;
474             }
475              
476             =head3 $self->clear_headers();
477              
478             Clears all custom headers defined for this message.
479              
480             =cut
481              
482             sub clear_headers {
483 0     0 1   my ($self) = @_;
484              
485 0           delete $self->{data}{headers};
486              
487 0           return $self;
488             }
489              
490             =head3 $self->set_headers(%headers);
491              
492             Sets all custom SMTP headers for this message at once. These must be properly encoded
493             if they contain unicode characters. Must not be one of the reserved headers.
494              
495             These can be overridden at the message personalization level.
496              
497             =cut
498              
499             sub set_headers {
500 0     0 1   my ($self, %headers) = @_;
501              
502 0           delete $self->{data}{headers};
503 0 0         $self->{data}{headers} = \%headers if %headers;
504              
505 0           return $self;
506             }
507              
508             =head3 $self->clear_categories();
509              
510             Clears out all categories defined for this message.
511              
512             =cut
513              
514             sub clear_categories {
515 0     0 1   my ($self) = @_;
516              
517 0           delete $self->{data}{categories};
518              
519 0           return $self;
520             }
521              
522             =head3 $self->set_categories(@categories);
523              
524             Sets the list of categories for this message. The list of categories must be
525             unique and contain no more than 10 items.
526              
527             =cut
528              
529             sub set_categories {
530 0     0 1   my ($self, @categories) = @_;
531              
532 0 0         croak "Cannot set more than 10 categories"
533             if scalar( @categories ) > 10;
534              
535 0           delete $self->{data}{categories};
536              
537 0 0         $self->{data}{categories} = \@categories if @categories;
538              
539 0           return $self;
540             }
541              
542             =head3 $self->add_category($name);
543              
544             Adds a new category for this message. The list of categories must be
545             unique and contain no more than 10 items.
546              
547             =cut
548              
549             sub add_category {
550 0     0 1   my ($self, $name) = @_;
551              
552 0 0         croak "Category name is required" unless $name;
553              
554 0   0       $self->{data}{categories} ||= [];
555              
556             croak "Cannot add more than 10 categories"
557 0 0         if scalar( @{ $self->{data}{categories} } ) > 9;
  0            
558              
559 0           push @{ $self->{data}{categories} }, $name;
  0            
560              
561 0           return $self;
562             }
563              
564             =head3 $self->clear_custom_args();
565              
566             Clears out all custom arguments defined for this message.
567              
568             =cut
569              
570             sub clear_custom_args {
571 0     0 1   my ($self) = @_;
572              
573 0           delete $self->{data}{custom_args};
574              
575 0           return $self;
576             }
577              
578             =head3 $self->set_custom_args(%args);
579              
580             Sets all custom arguments defined for this message.
581             These can be overridden at the message personalization level.
582             The total size of custom arguments cannot exceed 10,000 bytes.
583              
584             =cut
585              
586             sub set_custom_args {
587 0     0 1   my ($self, %args) = @_;
588              
589 0           delete $self->{data}{custom_args};
590              
591 0 0         $self->{data}{custom_args} = \%args if %args;
592              
593 0           return $self;
594             }
595              
596             =head3 $self->send_at($timestamp);
597              
598             A unix timestamp (seconds since 1970) specifying when to deliver this message.
599             Cannot be more than 72 hours in the future.
600              
601             This can be overridden at the message personalization level.
602              
603             =cut
604              
605             sub send_at {
606 0     0 1   my ($self, $timestamp) = @_;
607              
608 0           delete $self->{data}{send_at};
609 0 0         $self->{data}{send_at} = $timestamp if $timestamp;
610              
611 0           return $self;
612             }
613              
614             =head3 $self->batch_id($batch_id);
615              
616             Identifies a batch to include this message in. This batch ID can later be used
617             to pause or cancel the delivery of a batch (if a future delivery time was set)
618              
619             =cut
620              
621             sub batch_id {
622 0     0 1   my ($self, $batch_id) = @_;
623              
624 0           delete $self->{data}{batch_id};
625 0 0         $self->{data}{batch_id} = $batch_id if $batch_id;
626              
627 0           return $self;
628             }
629              
630             =head3 $self->unsubscribe_group($group_id, @display_groups);
631              
632             If you've set up multiple unsubscribe groups in the SendGrid web application, this method
633             allows you to specify which group this message belongs to. If this is set and the user
634             unsubscribes from this message, they will only be added to the suppression list for that
635             single group. If not set, they will be added to the global unsubscribe list.
636              
637             @display_groups is optional. If specified, when the user clicks "unsubscribe" they will be
638             shown a list of these groups and allowed to choose which ones he/she would like to unsubscribe
639             from.
640              
641             =cut
642              
643             sub unsubscribe_group {
644 0     0 1   my ($self, $group_id, @display_groups) = @_;
645              
646 0 0         croak "Unsubscribe group ID is required" unless $group_id;
647 0 0         croak "Cannot display more than 25 groups" if scalar(@display_groups) > 25;
648              
649 0           $self->{data}{asm} = { group_id => $group_id };
650 0 0         $self->{data}{asm}{groups_to_display} = \@display_groups if @display_groups;
651              
652 0           return $self;
653             }
654              
655             =head3 $self->ip_pool_name($pool_name);
656              
657             The IP Pool that you would like to send this email from.
658              
659             =cut
660              
661             sub ip_pool_name {
662 0     0 1   my ($self, $pool_name) = @_;
663              
664 0           delete $self->{data}{ip_pool_name};
665 0 0         $self->{data}{ip_pool_name} = $pool_name if $pool_name;
666              
667 0           return $self;
668             }
669              
670             =head3 $self->click_tracking($enable, %args);
671              
672             Whether to enable click-tracking for this message. If enabled, any URLs in the body of this
673             message will be rewritten to proxy through SendGrid for tracking purposes. This setting will
674             overwrite the account-level setting if any. One optional argument is accepted: 'enable_text'
675             which controls whether the link-rewriting is also performed for plaintext emails (the rewritten
676             URL will be visible to the recipient)
677              
678             =cut
679              
680             sub click_tracking {
681 0     0 1   my ($self, $enable, %args) = @_;
682              
683 0 0         $enable = $enable ? JSON::true : JSON::false;
684              
685 0   0       $self->{data}{tracking_settings} ||= {};
686 0           $self->{data}{tracking_settings}{click_tracking} = { enable => $enable };
687              
688 0 0         if (defined $args{enable_text}) {
689             $self->{data}{tracking_settings}{click_tracking}{enable_text} =
690 0 0         $args{enable_text} ? JSON::true : JSON::false;
691             }
692              
693 0           return $self;
694             }
695              
696             =head3 $self->open_tracking($enable, %args);
697              
698             Whether to enable open-tracking for this message. If enabled, a single transparent pixel image
699             is added to the HTML body of this message and used to determine if and when the recipient opens
700             the message. This setting will overwrite the account-level setting if any. One optional argument
701             is accepted: 'substitution_tag' which identifies a token in the message body that should be replaced
702             with the tracking pixel.
703              
704             =cut
705              
706             sub open_tracking {
707 0     0 1   my ($self, $enable, %args) = @_;
708              
709 0 0         $enable = $enable ? JSON::true : JSON::false;
710              
711 0   0       $self->{data}{tracking_settings} ||= {};
712 0           $self->{data}{tracking_settings}{open_tracking} = { enable => $enable };
713             $self->{data}{tracking_settings}{open_tracking}{substitution_tag} =
714 0 0         $args{substitution_tag} if $args{substitution_tag};
715              
716 0           return $self;
717             }
718              
719             =head3 $self->subscription_tracking($enable, %args);
720              
721             Whether to enable a sendgrid-powered unsubscribe link in the footer of the email. You may pass
722             optional arguments 'text' and 'html' to control the verbiage of the unsubscribe link used, OR
723             'substitution_tag' which is a token that will be replaced with the unsubscribe URL.
724             This setting will overwrite the account-level setting if any.
725              
726             =cut
727              
728             sub subscription_tracking {
729 0     0 1   my ($self, $enable, %args) = @_;
730              
731 0 0         $enable = $enable ? JSON::true : JSON::false;
732              
733 0           my $new = { enable => $enable };
734 0 0         $new->{text} = $args{text} if $args{text};
735 0 0         $new->{html} = $args{html} if $args{html};
736 0 0         $new->{substitution_tag} = $args{substitution_tag} if $args{substitution_tag};
737              
738 0   0       $self->{data}{tracking_settings} ||= {};
739 0           $self->{data}{tracking_settings}{subscription_tracking} = $new;
740              
741 0           return $self;
742             }
743              
744             =head3 $self->ganalytics($enable, %args);
745              
746             Whether to enable google analytics tracking for this message. Optional arguments
747             include 'utm_source', 'utm_medium', 'utm_term', 'utm_content', and 'utm_campaign'.
748             This setting will overwrite the account-level setting if any.
749              
750             =cut
751              
752             sub ganalytics {
753 0     0 1   my ($self, $enable, %args) = @_;
754              
755 0 0         $enable = $enable ? JSON::true : JSON::false;
756              
757 0           my $new = { enable => $enable };
758 0 0         $new->{utm_source} = $args{utm_source} if $args{utm_source};
759 0 0         $new->{utm_medium} = $args{utm_medium} if $args{utm_medium};
760 0 0         $new->{utm_term} = $args{utm_term} if $args{utm_term};
761 0 0         $new->{utm_content} = $args{utm_content} if $args{utm_content};
762 0 0         $new->{utm_campaign} = $args{utm_campaign} if $args{utm_campaign};
763              
764 0   0       $self->{data}{tracking_settings} ||= {};
765 0           $self->{data}{tracking_settings}{ganalytics} = $new;
766              
767 0           return $self;
768             }
769              
770             =head3 $self->bcc($enable, %args);
771              
772             Whether to BCC a monitoring account when sending this message. Optional arguments
773             include 'email' for the address that will receive the BCC if one is not configured
774             at the account level. This setting will overwrite the account-level setting if any.
775              
776             =cut
777              
778             sub bcc {
779 0     0 1   my ($self, $enable, %args) = @_;
780              
781 0 0         $enable = $enable ? JSON::true : JSON::false;
782              
783 0   0       $self->{data}{mail_settings} ||= {};
784 0           $self->{data}{mail_settings}{bcc} = { enable => $enable };
785 0 0         $self->{data}{mail_settings}{bcc}{email} = $args{email} if $args{email};
786              
787 0           return $self;
788             }
789              
790             =head3 $self->bypass_list_management($enable);
791              
792             Whether to bypass the built-in suppression SendGrid provides, such as unsubscribed
793             recipients, those that have bounced, or marked the emails as spam.
794             This setting will overwrite the account-level setting if any.
795              
796             =cut
797              
798             sub bypass_list_management {
799 0     0 1   my ($self, $enable, %args) = @_;
800              
801 0 0         $enable = $enable ? JSON::true : JSON::false;
802              
803 0   0       $self->{data}{mail_settings} ||= {};
804 0           $self->{data}{mail_settings}{bypass_list_management} = { enable => $enable };
805              
806 0           return $self;
807             }
808              
809             =head3 $self->footer($enable, %args);
810              
811             Whether to add a footer to the outgoing message. Optional arguments include 'html' and
812             'text' to specify the footers that will be used for each message body type.
813             This setting will overwrite the account-level setting if any.
814              
815             =cut
816              
817             sub footer {
818 0     0 1   my ($self, $enable, %args) = @_;
819              
820 0 0         $enable = $enable ? JSON::true : JSON::false;
821              
822 0   0       $self->{data}{mail_settings} ||= {};
823 0           $self->{data}{mail_settings}{footer} = { enable => $enable };
824 0 0         $self->{data}{mail_settings}{footer}{text} = $args{text} if $args{text};
825 0 0         $self->{data}{mail_settings}{footer}{html} = $args{html} if $args{html};
826              
827 0           return $self;
828             }
829              
830             =head3 $self->sandbox_mode($enable);
831              
832             Whether to enable sandbox mode. When enabled, SendGrid will validate the contents of this
833             API request for correctness, but will not actually send the message.
834              
835             =cut
836              
837             sub sandbox_mode {
838 0     0 1   my ($self, $enable, %args) = @_;
839              
840 0 0         $enable = $enable ? JSON::true : JSON::false;
841              
842 0   0       $self->{data}{mail_settings} ||= {};
843 0           $self->{data}{mail_settings}{sandbox_mode} = { enable => $enable };
844              
845 0           return $self;
846             }
847              
848             =head3 $self->spam_check($enable, %args);
849              
850             Whether to perform a spam check on this message prior to sending. If the message fails the
851             spam check, it will be dropped and not sent. Optional parameters include 'threshold' - an
852             integer score value from 1-10 (default 5) over which a message will be classified as spam,
853             and 'post_to_url' - a SendGrid inbound message parsing URL that will be used to post back
854             notifications of messages identified as spam and dropped. These settings will overwrite
855             the account-level settings if any.
856              
857             =cut
858              
859             sub spam_check {
860 0     0 1   my ($self, $enable, %args) = @_;
861              
862 0 0         $enable = $enable ? JSON::true : JSON::false;
863              
864 0   0       $self->{data}{mail_settings} ||= {};
865 0           $self->{data}{mail_settings}{spam_check} = { enable => $enable };
866 0 0         $self->{data}{mail_settings}{spam_check}{threshold} = $args{threshold} if $args{threshold};
867 0 0         $self->{data}{mail_settings}{spam_check}{post_to_url} = $args{post_to_url} if $args{post_to_url};
868              
869 0           return $self;
870             }
871              
872             =head1 AUTHOR
873              
874             Grant Street Group
875              
876             =head1 LICENSE AND COPYRIGHT
877              
878             Copyright 2018 Grant Street Group.
879              
880             This program is free software; you can redistribute it and/or modify it
881             under the terms of the the Artistic License (2.0). You may obtain a
882             copy of the full license at:
883              
884             L
885              
886             =cut
887              
888             1;