File Coverage

blib/lib/Email/Abstract.pm
Criterion Covered Total %
statement 69 69 100.0
branch 30 30 100.0
condition 5 5 100.0
subroutine 15 15 100.0
pod 3 3 100.0
total 122 122 100.0


line stmt bran cond sub pod time code
1 3     3   53343 use 5.006;
  3         12  
  3         115  
2 3     3   13 use warnings;
  3         7  
  3         104  
3 3     3   17 use strict;
  3         4  
  3         190  
4             package Email::Abstract;
5             # ABSTRACT: unified interface to mail representations
6             $Email::Abstract::VERSION = '3.008';
7 3     3   18 use Carp;
  3         4  
  3         280  
8 3     3   896 use Email::Simple;
  3         8256  
  3         100  
9 3     3   1962 use MRO::Compat;
  3         10119  
  3         150  
10              
11             use Module::Pluggable 1.5
12 3         29 search_path => [__PACKAGE__],
13             except => 'Email::Abstract::Plugin',
14 3     3   2514 require => 1;
  3         33597  
15              
16 3     3   278 use Scalar::Util ();
  3         6  
  3         1693  
17              
18             my @plugins = __PACKAGE__->plugins(); # Requires them.
19             my %adapter_for =
20             map { $_->target => $_ }
21             grep {
22             my $avail = eval { $_->is_available };
23             $@ ? ($@ =~ /Can't locate object method "is_available"/) : $avail;
24             }
25             @plugins;
26              
27             sub object {
28 82     82 1 75 my ($self) = @_;
29 82 100       209 return unless ref $self;
30 37         84 return $self->[0];
31             }
32              
33             sub new {
34 13     13 1 11734 my ($class, $foreign) = @_;
35              
36 13 100       23 return $foreign if eval { $foreign->isa($class) };
  13         162  
37              
38 11 100       62 $foreign = Email::Simple->new($foreign)
39             unless Scalar::Util::blessed($foreign);
40              
41 11         1843 my $adapter = $class->__class_for($foreign); # dies if none available
42 9         34 return bless [ $foreign, $adapter ] => $class;
43             }
44              
45             sub __class_for {
46 61     61   2967 my ($self, $foreign, $method, $skip_super) = @_;
47 61   100     207 $method ||= 'handle';
48              
49 61         67 my $f_class = ref $foreign;
50 61 100       152 $f_class = $foreign unless $f_class;
51              
52 61 100 100     352 return $f_class if ref $foreign and $f_class->isa($self);
53              
54 49 100       146 return $adapter_for{$f_class} if $adapter_for{$f_class};
55              
56 5 100       18 if (not $skip_super) {
57 4         10 my @bases = @{ mro::get_linear_isa($f_class) };
  4         44  
58 4         8 shift @bases;
59 4         13 for my $base (@bases) {
60 3 100       21 return $adapter_for{$base} if $adapter_for{$base};
61             }
62             }
63              
64 3         693 Carp::croak "Don't know how to $method $f_class";
65             }
66              
67             sub _adapter_obj_and_args {
68 70     70   62 my $self = shift;
69              
70 70 100       113 if (my $thing = $self->object) {
71 25         63 return ($self->[1], $thing, @_);
72             } else {
73 45         48 my $thing = shift;
74 45 100       181 my $adapter = $self->__class_for(
75             Scalar::Util::blessed($thing) ? $thing : 'Email::Simple'
76             );
77 45         111 return ($adapter, $thing, @_);
78             }
79             }
80              
81             for my $func (qw(get_header get_body set_header set_body as_string)) {
82 3     3   20 no strict 'refs';
  3         5  
  3         887  
83             *$func = sub {
84 66     66   23203 my $self = shift;
85 66         137 my ($adapter, $thing, @args) = $self->_adapter_obj_and_args(@_);
86              
87             # In the event of Email::Abstract->get_body($email_abstract), convert
88             # it into an object method call.
89 66 100       196 $thing = $thing->object if eval { $thing->isa($self) };
  66         425  
90              
91             # I suppose we could work around this by leaving @_ intact and assigning to
92             # it. That seems ... not good. -- rjbs, 2007-07-18
93 66 100       185 unless (Scalar::Util::blessed($thing)) {
94 10 100       581 Carp::croak "can't alter string in place" if substr($func, 0, 3) eq 'set';
95 3         11 $thing = Email::Simple->new(
96 6 100       20 ref $thing ? \do{my$str=$$thing} : $thing
97             );
98             }
99              
100 62         1985 return $adapter->$func($thing, @args);
101             };
102             }
103              
104             sub cast {
105 4     4 1 2954 my $self = shift;
106 4         15 my ($from_adapter, $from, $to) = $self->_adapter_obj_and_args(@_);
107              
108 4         12 my $adapter = $self->__class_for($to, 'construct', 1);
109              
110 3 100       10 my $from_string = ref($from) ? $from_adapter->as_string($from) : $from;
111              
112 3         90 return $adapter->construct($from_string);
113             }
114              
115             1;
116              
117             =pod
118              
119             =encoding UTF-8
120              
121             =head1 NAME
122              
123             Email::Abstract - unified interface to mail representations
124              
125             =head1 VERSION
126              
127             version 3.008
128              
129             =head1 SYNOPSIS
130              
131             my $message = Mail::Message->read($rfc822)
132             || Email::Simple->new($rfc822)
133             || Mail::Internet->new([split /\n/, $rfc822])
134             || ...
135             || $rfc822;
136              
137             my $email = Email::Abstract->new($message);
138              
139             my $subject = $email->get_header("Subject");
140             $email->set_header(Subject => "My new subject");
141              
142             my $body = $email->get_body;
143              
144             $rfc822 = $email->as_string;
145              
146             my $mail_message = $email->cast("Mail::Message");
147              
148             =head1 DESCRIPTION
149              
150             C provides module writers with the ability to write
151             simple, representation-independent mail handling code. For instance, in the
152             cases of C or C, a key part of the code
153             involves reading the headers from a mail object. Where previously one would
154             either have to specify the mail class required, or to build a new object from
155             scratch, C can be used to perform certain simple operations on
156             an object regardless of its underlying representation.
157              
158             C currently supports C, C,
159             C, C, C, and C. Other
160             representations are encouraged to create their own C class
161             by copying C. All modules installed under the
162             C hierarchy will be automatically picked up and used.
163              
164             =head1 METHODS
165              
166             All of these methods may be called either as object methods or as class
167             methods. When called as class methods, the email object (of any class
168             supported by Email::Abstract) must be prepended to the list of arguments, like
169             so:
170              
171             my $return = Email::Abstract->method($message, @args);
172              
173             This is provided primarily for backwards compatibility.
174              
175             =head2 new
176              
177             my $email = Email::Abstract->new($message);
178              
179             Given a message, either as a string or as an object for which an adapter is
180             installed, this method will return a Email::Abstract object wrapping the
181             message.
182              
183             If the message is given as a string, it will be used to construct an object,
184             which will then be wrapped.
185              
186             =head2 get_header
187              
188             my $header = $email->get_header($header_name);
189              
190             my @headers = $email->get_header($header_name);
191              
192             This returns the values for the given header. In scalar context, it returns
193             the first value.
194              
195             =head2 set_header
196              
197             $email->set_header($header => @values);
198              
199             This sets the C<$header> header to the given one or more values.
200              
201             =head2 get_body
202              
203             my $body = $email->get_body;
204              
205             This returns the body as a string.
206              
207             =head2 set_body
208              
209             $email->set_body($string);
210              
211             This changes the body of the email to the given string.
212              
213             B You probably don't want to call this method, despite what you may
214             think. Email message bodies are complicated, and rely on things like content
215             type, encoding, and various MIME requirements. If you call C on a
216             message more complicated than a single-part seven-bit plain-text message, you
217             are likely to break something. If you need to do this sort of thing, you
218             should probably use a specific message class from end to end.
219              
220             This method is left in place for backwards compatibility.
221              
222             =head2 as_string
223              
224             my $string = $email->as_string;
225              
226             This returns the whole email as a decoded string.
227              
228             =head2 cast
229              
230             my $mime_entity = $email->cast('MIME::Entity');
231              
232             This method will convert a message from one message class to another. It will
233             throw an exception if no adapter for the target class is known, or if the
234             adapter does not provide a C method.
235              
236             =head2 object
237              
238             my $message = $email->object;
239              
240             This method returns the message object wrapped by Email::Abstract. If called
241             as a class method, it returns false.
242              
243             Note that, because strings are converted to message objects before wrapping,
244             this method will return an object when the Email::Abstract was constructed from
245             a string.
246              
247             =head1 AUTHORS
248              
249             =over 4
250              
251             =item *
252              
253             Ricardo SIGNES
254              
255             =item *
256              
257             Simon Cozens
258              
259             =item *
260              
261             Casey West
262              
263             =back
264              
265             =head1 COPYRIGHT AND LICENSE
266              
267             This software is copyright (c) 2004 by Simon Cozens.
268              
269             This is free software; you can redistribute it and/or modify it under
270             the same terms as the Perl 5 programming language system itself.
271              
272             =cut
273              
274             __END__