File Coverage

blib/lib/Mail/SendGrid.pm
Criterion Covered Total %
statement 26 73 35.6
branch 0 16 0.0
condition 0 3 0.0
subroutine 9 12 75.0
pod 2 2 100.0
total 37 106 34.9


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