File Coverage

blib/lib/Email/SendGrid/V3.pm
Criterion Covered Total %
statement 86 254 33.8
branch 25 144 17.3
condition 7 42 16.6
subroutine 17 48 35.4
pod 37 37 100.0
total 172 525 32.7


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