File Coverage

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


line stmt bran cond sub pod time code
1 3     3   80173 use 5.006;
  3         19  
2 3     3   17 use warnings;
  3         6  
  3         82  
3 3     3   13 use strict;
  3         5  
  3         126  
4             package Email::Abstract;
5             # ABSTRACT: unified interface to mail representations
6             $Email::Abstract::VERSION = '3.010';
7 3     3   16 use Carp;
  3         14  
  3         179  
8 3     3   945 use Email::Simple;
  3         10172  
  3         84  
9 3     3   1372 use MRO::Compat;
  3         5359  
  3         134  
10              
11             use Module::Pluggable 1.5
12 3         22 search_path => [__PACKAGE__],
13             except => 'Email::Abstract::Plugin',
14 3     3   1419 require => 1;
  3         33329  
15              
16 3     3   311 use Scalar::Util ();
  3         16  
  3         1442  
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 125 my ($self) = @_;
29 82 100       248 return unless ref $self;
30 37         100 return $self->[0];
31             }
32              
33             sub new {
34 13     13 1 31839 my ($class, $foreign) = @_;
35              
36 13 100       27 return $foreign if eval { $foreign->isa($class) };
  13         135  
37              
38 11 100       71 $foreign = Email::Simple->new($foreign)
39             unless Scalar::Util::blessed($foreign);
40              
41 11         2743 my $adapter = $class->__class_for($foreign); # dies if none available
42 9         37 return bless [ $foreign, $adapter ] => $class;
43             }
44              
45             sub __class_for {
46 61     61   10673 my ($self, $foreign, $method, $skip_super) = @_;
47 61   100     237 $method ||= 'handle';
48              
49 61         99 my $f_class = ref $foreign;
50 61 100       113 $f_class = $foreign unless $f_class;
51              
52 61 100 100     260 return $f_class if ref $foreign and $f_class->isa($self);
53              
54 49 100       186 return $adapter_for{$f_class} if $adapter_for{$f_class};
55              
56 5 100       12 if (not $skip_super) {
57 4         6 my @bases = @{ mro::get_linear_isa($f_class) };
  4         21  
58 4         8 shift @bases;
59 4         10 for my $base (@bases) {
60 3 100       15 return $adapter_for{$base} if $adapter_for{$base};
61             }
62             }
63              
64 3         378 Carp::croak "Don't know how to $method $f_class";
65             }
66              
67             sub _adapter_obj_and_args {
68 70     70   107 my $self = shift;
69              
70 70 100       150 if (my $thing = $self->object) {
71 25         89 return ($self->[1], $thing, @_);
72             } else {
73 45         83 my $thing = shift;
74 45 100       159 my $adapter = $self->__class_for(
75             Scalar::Util::blessed($thing) ? $thing : 'Email::Simple'
76             );
77 45         153 return ($adapter, $thing, @_);
78             }
79             }
80              
81             for my $func (qw(get_header get_body set_header set_body as_string)) {
82 3     3   23 no strict 'refs';
  3         15  
  3         896  
83             *$func = sub {
84 66     66   35667 my $self = shift;
85 66         178 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       115 $thing = $thing->object if eval { $thing->isa($self) };
  66         401  
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       209 unless (Scalar::Util::blessed($thing)) {
94 10 100       627 Carp::croak "can't alter string in place" if substr($func, 0, 3) eq 'set';
95             $thing = Email::Simple->new(
96 6 100       22 ref $thing ? \do{my$str=$$thing} : $thing
  3         14  
97             );
98             }
99              
100 62         2913 return $adapter->$func($thing, @args);
101             };
102             }
103              
104             sub cast {
105 4     4 1 3608 my $self = shift;
106 4         13 my ($from_adapter, $from, $to) = $self->_adapter_obj_and_args(@_);
107              
108 4         14 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         138 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.010
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 PERL VERSION
165              
166             This library should run on perls released even a long time ago. It should
167             work on any version of perl released in the last five years.
168              
169             Although it may work on older versions of perl, no guarantee is made that the
170             minimum required version will not be increased. The version may be increased
171             for any reason, and there is no promise that patches will be accepted to
172             lower the minimum required perl.
173              
174             =head1 METHODS
175              
176             All of these methods may be called either as object methods or as class
177             methods. When called as class methods, the email object (of any class
178             supported by Email::Abstract) must be prepended to the list of arguments, like
179             so:
180              
181             my $return = Email::Abstract->method($message, @args);
182              
183             This is provided primarily for backwards compatibility.
184              
185             =head2 new
186              
187             my $email = Email::Abstract->new($message);
188              
189             Given a message, either as a string or as an object for which an adapter is
190             installed, this method will return a Email::Abstract object wrapping the
191             message.
192              
193             If the message is given as a string, it will be used to construct an object,
194             which will then be wrapped.
195              
196             =head2 get_header
197              
198             my $header = $email->get_header($header_name);
199              
200             my @headers = $email->get_header($header_name);
201              
202             This returns the values for the given header. In scalar context, it returns
203             the first value.
204              
205             =head2 set_header
206              
207             $email->set_header($header => @values);
208              
209             This sets the C<$header> header to the given one or more values.
210              
211             =head2 get_body
212              
213             my $body = $email->get_body;
214              
215             This returns the body as a string.
216              
217             =head2 set_body
218              
219             $email->set_body($string);
220              
221             This changes the body of the email to the given string.
222              
223             B You probably don't want to call this method, despite what you may
224             think. Email message bodies are complicated, and rely on things like content
225             type, encoding, and various MIME requirements. If you call C on a
226             message more complicated than a single-part seven-bit plain-text message, you
227             are likely to break something. If you need to do this sort of thing, you
228             should probably use a specific message class from end to end.
229              
230             This method is left in place for backwards compatibility.
231              
232             =head2 as_string
233              
234             my $string = $email->as_string;
235              
236             This returns the whole email as a decoded string.
237              
238             =head2 cast
239              
240             my $mime_entity = $email->cast('MIME::Entity');
241              
242             This method will convert a message from one message class to another. It will
243             throw an exception if no adapter for the target class is known, or if the
244             adapter does not provide a C method.
245              
246             =head2 object
247              
248             my $message = $email->object;
249              
250             This method returns the message object wrapped by Email::Abstract. If called
251             as a class method, it returns false.
252              
253             Note that, because strings are converted to message objects before wrapping,
254             this method will return an object when the Email::Abstract was constructed from
255             a string.
256              
257             =head1 AUTHORS
258              
259             =over 4
260              
261             =item *
262              
263             Ricardo SIGNES
264              
265             =item *
266              
267             Simon Cozens
268              
269             =item *
270              
271             Casey West
272              
273             =back
274              
275             =head1 CONTRIBUTORS
276              
277             =for stopwords Dave Rolsky Ricardo Signes William Yardley
278              
279             =over 4
280              
281             =item *
282              
283             Dave Rolsky
284              
285             =item *
286              
287             Ricardo Signes
288              
289             =item *
290              
291             William Yardley
292              
293             =back
294              
295             =head1 COPYRIGHT AND LICENSE
296              
297             This software is copyright (c) 2004 by Simon Cozens.
298              
299             This is free software; you can redistribute it and/or modify it under
300             the same terms as the Perl 5 programming language system itself.
301              
302             =cut
303              
304             __END__