File Coverage

blib/lib/Net/FS/Gmail.pm
Criterion Covered Total %
statement 15 92 16.3
branch 0 28 0.0
condition 0 6 0.0
subroutine 5 14 35.7
pod 8 8 100.0
total 28 148 18.9


line stmt bran cond sub pod time code
1             package Net::FS::Gmail;
2              
3 1     1   818 use strict;
  1         1  
  1         38  
4 1     1   1265 use Mail::Webmail::Gmail;
  1         86065  
  1         69  
5 1     1   22 use File::Basename;
  1         1  
  1         67  
6 1     1   839 use Time::ParseDate;
  1         14712  
  1         86  
7 1     1   15 use URI::Escape;
  1         2  
  1         1292  
8             our $VERSION = "0.2";
9             our $FILESTORE_VERSION = "0.1"; # this way we can track different revisions of filestore format
10              
11             =head1 NAME
12              
13             Net::FS::Gmail - store and retrieve files on Gmail
14              
15             =head1 SYNOPSIS
16              
17             my $fs = Net::FS::Gmail->new( username => $user, password => $pass );
18              
19             $fs->store("file.txt");
20             $fs->store("piccy.jpg", "renamed_piccy.jpg");
21              
22             open (FILE, ">output.jpg") || die "Couldn't write to file: $!\n";
23             binmode (FILE);
24             print FILE $fs->retrieve("renamed_piccy.jpg");
25             close (FILE);
26              
27              
28             =head1 METHODS
29              
30             =cut
31              
32             =head2 new
33              
34             Takes the same options as Mail::Webmail::Gmail
35              
36             =cut
37              
38             sub new {
39 0     0 1   my $class = shift;
40 0           my %opts = @_;
41 0           my $gmail = Mail::Webmail::Gmail->new( %opts );
42             # TODO better error reporting
43 0 0         $gmail->login() || die "Couldn't log into gmail : ".$gmail->error_msg();
44 0           my $self = { _gmail => $gmail, _user => $opts{username} };
45 0           return bless $self, $class;
46             }
47              
48              
49             =head2 store [as]
50              
51             Store the file on Gmail. If a second filename is given then use that
52             as the name on GMail
53              
54             =cut
55              
56             sub store {
57 0     0 1   my $self = shift;
58 0           my $file = shift;
59 0 0         my $as = shift; $as = $file unless defined $as;
  0            
60 0 0         die "No such file $file\n" unless -f $file;
61              
62 0           my $subject = "GmailStore v$FILESTORE_VERSION $as";
63 0 0         my $user = $self->{_user}; $user .= '@googlemail.com' unless $user =~ m!\@googlemail\.com$!;
  0            
64              
65 0           $self->{_gmail}->send_message( to => $user, subject => $subject, msgbody => '', file0 => [ $file ] );
66             }
67              
68              
69              
70             =head2 retrieve [version]
71              
72             Get from Gmail.
73              
74             If the file has multiple versions then you can pass in a version number to get version
75             - 1 being the oldest. If you don't pass in a version then you get the latest.
76              
77              
78             =cut
79              
80             sub retrieve {
81 0     0 1   my $self = shift;
82 0           my $file = shift;
83 0           my $version = shift;
84              
85 0           my @versions = $self->versions($file);
86              
87 0 0         die "Couldn't find $file\n" unless @versions;
88              
89 0           my $mid;
90 0 0 0       if (!defined $version) {
    0          
91 0           $mid = $versions[0]->{id};
92             } elsif ($version > @versions || $version < 1) {
93 0           die "No such version $version\n";
94             } else {
95 0           $mid = $versions[-$version]->{id};
96             }
97              
98 0           my $message = $self->{_gmail}->get_indv_email( id => $mid, label => $Mail::Webmail::Gmail::FOLDERS{ 'INBOX' } )->{$mid};
99              
100              
101 0 0         die "Error: couldn't get attachments\n" unless defined $message->{ 'attachments' };
102 0           my $attachment = $self->{_gmail}->get_attachment( attachment => $message->{ 'attachments' }->[0] );
103 0 0         if ( $self->{_gmail}->error() ) {
104 0           die $self->{_gmail}-error_msg()."\n";
105             }
106 0           return $$attachment;
107             }
108              
109             =head2 versions
110              
111             Returns a list of all the versions of a file
112              
113             Each item on the list is a hashref containing the date the file was saved
114             and the id of that version using the keys I and I respectively.
115              
116             The list is sorted, latest version first.
117              
118             =cut
119              
120             sub versions {
121 0     0 1   my $self = shift;
122 0           my $file = shift;
123 0           my @versions;
124 0           foreach my $message (@{$self->{_gmail}->get_messages()}) {
  0            
125 0           my $email = $self->{_gmail}->get_indv_email( msg => $message );
126 0           foreach my $id (keys %$email) {
127 0           my $item = $email->{$id};
128             # TODO the subject may be html encoded
129 0 0         next unless uri_unescape($item->{'subject'}) =~ m!^GmailStore v[\d.]+ $file$!;
130             # TODO the sent time may be html encoded and need to be de-unicoded (7½ hours ago for example)
131 0           my $epoch_date = parsedate($item->{'sent'});
132 0           push @versions, { id => $id, timestamp => $epoch_date };
133             }
134             }
135 0           return sort { $b->{timestamp} <=> $a->{timestamp} } @versions;
  0            
136             }
137              
138              
139             =head2 files
140              
141             Get a list of all the files on the system
142              
143             =cut
144              
145             sub files {
146 0     0 1   my $self = shift;
147              
148 0           my @files;
149 0           foreach my $message (@{$self->{_gmail}->get_messages()}) {
  0            
150             # we do this to force it to be read
151 0           my $email = $self->{_gmail}->get_indv_email( msg => $message );
152 0           my $subject = uri_unescape((values(%$email))[0]->{subject});
153 0 0         next unless $subject =~ m!^GmailStore v[\d.]+ !;
154 0           push @files, $';
155             }
156 0           return @files;
157             }
158              
159              
160             =head2 delete [version]
161              
162             Delete a file. If you pass a version number than only delete that version.
163              
164             =cut
165              
166             sub delete {
167 0     0 1   my $self = shift;
168 0           my $file = shift;
169 0           my $version = shift;
170            
171 0           $self->_delete($file, 1, $version);
172             }
173              
174             =head2 remove [version]
175              
176             The same as remove except that the file is merely moved to the trash.
177              
178             =cut
179              
180             sub remove {
181 0     0 1   my $self = shift;
182 0           my $file = shift;
183 0           my $version = shift;
184            
185 0           $self->_delete($file, 0, $version);
186             }
187              
188              
189             sub _delete {
190 0     0     my $self = shift;
191 0           my $file = shift;
192 0           my $delete = shift;
193 0           my $version = shift;
194              
195              
196 0           my @versions = $self->versions($file);
197              
198 0 0         die "Couldn't find $file\n" unless @versions;
199              
200 0           my @mids;
201 0 0 0       if (!defined $version) {
    0          
202 0           @mids = map { $_->{id} } @versions;
  0            
203             } elsif ($version > @versions || $version < 1) {
204 0           die "No such version $version\n";
205             } else {
206 0           push @mids, $versions[-$version]->{id};
207             }
208 0           print STDERR "Deleting ".join(", ", @mids)."\n";
209            
210 0           $self->{_gmail}->delete_message( msgid => [ @mids ], del_message => $delete );
211              
212              
213             }
214              
215              
216             =head2 quota
217              
218             Get your current remaining quota, just like in Mail::Webmail::Gmail i.e
219             returns a scalar with the amount of MB remaining in you account.
220              
221             If called in list context, returns an array as follows:
222              
223             [ Used, Total, Percent Used ] [ "0 MB", "1000 MB", "0%" ]
224              
225             =cut
226              
227             sub quota {
228 0     0 1   my $self = shift;
229 0           return $self->{_gmail}->size_usage();
230             }
231              
232              
233             =head1 AUTHOR
234              
235             Simon Wistow
236              
237             =head1 COPYRIGHT
238              
239             Copyright 2006, Simon Wistow
240              
241             Released under the same terms as Perl itself
242              
243             =cut
244              
245              
246              
247              
248             1;