File Coverage

blib/lib/Mail/SendGrid.pm
Criterion Covered Total %
statement 27 74 36.4
branch 0 16 0.0
condition 0 3 0.0
subroutine 9 12 75.0
pod 2 2 100.0
total 38 107 35.5


line stmt bran cond sub pod time code
1 2     2   22526 use strict;
  2         4  
  2         76  
2 2     2   11 use warnings;
  2         4  
  2         104  
3             package Mail::SendGrid;
4             {
5             $Mail::SendGrid::VERSION = '0.07';
6             }
7             # ABSTRACT: interface to SendGrid.com mail gateway APIs
8              
9 2     2   49 use 5.008;
  2         17  
  2         85  
10 2     2   1650 use Mouse 0.94;
  2         74619  
  2         14  
11 2     2   3129 use HTTP::Tiny 0.013;
  2         118168  
  2         88  
12 2     2   1259 use JSON 2.53;
  2         14976  
  2         20  
13 2     2   2008 use URI::Escape 3.30;
  2         2811  
  2         151  
14 2     2   12 use Carp 1.20;
  2         43  
  2         122  
15              
16 2     2   1146 use Mail::SendGrid::Bounce;
  2         5  
  2         1783  
17              
18             has 'api_user' => (is => 'ro', isa => 'Str', required => 1);
19             has 'api_key' => (is => 'ro', isa => 'Str', required => 1);
20             has 'ua' => (is => 'ro', default => sub { HTTP::Tiny->new(); });
21              
22             my %valid_params =
23             (
24              
25             'bounces.get' =>
26             {
27             days => '\d+',
28             start_date => '\d\d\d\d-\d\d-\d\d',
29             end_date => '\d\d\d\d-\d\d-\d\d',
30             limit => '\d+',
31             offset => '\d+',
32             type => 'hard|soft',
33             email => '\S+@\S+',
34             },
35              
36             'bounces.delete' =>
37             {
38             start_date => '\d\d\d\d-\d\d-\d\d',
39             end_date => '\d\d\d\d-\d\d-\d\d',
40             type => 'hard|soft',
41             email => '\S+@\S+',
42             },
43              
44             );
45              
46             sub bounces
47             {
48 0     0 1   my $self = shift;
49 0           my %opts = @_;
50 0           my $response;
51             my $url;
52 0           my $bounce_list;
53 0           my (@bounces, $bounce);
54              
55 0           $response = $self->_make_request('bounces.get', \%opts, { date => 1 });
56              
57 0 0         if ($response->{success}) {
58 0           $bounce_list = decode_json($response->{content});
59 0           foreach my $bounce_details (@{ $bounce_list }) {
  0            
60 0           $bounce = Mail::SendGrid::Bounce->new($bounce_details);
61 0 0         push(@bounces, $bounce) if defined($bounce);
62             }
63             }
64              
65 0           return @bounces;
66             }
67              
68             sub delete_bounces
69             {
70 0     0 1   my $self = shift;
71 0           my %opts = @_;
72 0           my $base_uri = 'https://sendgrid.com/api/bounces.delete.json';
73 0           my $response;
74             my $json;
75 0           my $url;
76              
77 0           $response = $self->_make_request('bounces.delete', \%opts, {});
78              
79 0 0         if ($response->{success}) {
80 0           $json = decode_json($response->{content});
81 0 0         if ($json->{message} eq 'success') {
    0          
82 0           return 1;
83             } elsif (exists($json->{message})) {
84 0           carp "bounces.delete failed - error message: $json->{message}\n";
85             } else {
86 0           carp "unexpected response from SendGrid: $response->{content}\n";
87             }
88             }
89              
90 0           return 0;
91             }
92              
93             #
94             # _make_request
95             #
96             # Helper function to build the URL and then make the request to SendGrid
97             # $action is the part of the endpoint that identifies the action
98             # eg for getting bounces, the base URL is https://sendgrid.com/api/bounces.get.json
99             # and $action will be 'bounces.get'
100             # $optref is a hash reference that contains any options passed by the caller of the
101             # public function
102             # $defaults is a hashref containing any defaults that we want to mix in,
103             # regardless of what the user passed to the public function
104             #
105             sub _make_request
106             {
107 0     0     my $self = shift;
108 0           my $action = shift;
109 0           my $optref = shift;
110 0           my $defaults = shift;
111 0           my %params = (
112             api_user => $self->api_user,
113             api_key => $self->api_key,
114             %$defaults,
115             );
116 0           my $url = 'https://sendgrid.com/api/'.$action.'.json';
117 0           my $response;
118              
119 0           foreach my $opt (keys %$optref) {
120 0 0         if (not exists($valid_params{$action}->{$opt})) {
121 0           carp "Mail::SendGrid unknown parameter '$opt' for $action";
122 0           return 0;
123             }
124 0 0 0       if ((not defined($optref->{$opt})) || ($optref->{$opt} !~ /^($valid_params{$action}->{$opt})$/)) {
125 0           carp "Mail::SendGrid invalid value '$optref->{$opt}' for parameter '$opt' to $action";
126 0           return 0;
127             }
128 0           $params{$opt} = $optref->{$opt};
129             }
130              
131 0           $url .= '?'.join('&', map { $_.'='.uri_escape($params{$_}) } keys %params);
  0            
132              
133 0           $response = $self->ua->get($url);
134 0 0         if (not $response->{success}) {
135 0           carp __PACKAGE__, " : $action HTTP request failed\n",
136             " status code = $response->{status}\n",
137             " reason = $response->{reason}\n";
138             }
139              
140 0           return $response;
141             }
142              
143             1;
144              
145             __END__