/[suikacvs]/messaging/manakai/lib/Message/Entity.pm
Suika

Contents of /messaging/manakai/lib/Message/Entity.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.37 - (hide annotations) (download)
Sun Aug 4 00:16:32 2002 UTC (23 years, 11 months ago) by wakaba
Branch: MAIN
Changes since 1.36: +104 -43 lines
2002-08-04  Wakaba <w@suika.fam.cx>

	* Entity.pm: Don't fill_source by default if format =~ http.

1 wakaba 1.1
2     =head1 NAME
3    
4     Message::Entity Perl module
5    
6     =head1 DESCRIPTION
7    
8     Perl module for RFC 822/2822 C<message>.
9     MIME multipart will be also supported (but not implemented yet).
10    
11     =cut
12    
13 wakaba 1.37 require 5.6.0; ## (require: v5.6.0 data type)
14 wakaba 1.1 package Message::Entity;
15     use strict;
16 wakaba 1.37 use vars qw(%DEFAULT %REG $VERSION);
17     $VERSION=do{my @r=(q$Revision: 1.36 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
18 wakaba 1.1
19 wakaba 1.15 require Message::Util;
20 wakaba 1.8 require Message::Header;
21 wakaba 1.15 require Message::MIME::MediaType;
22     require Message::MIME::Encoding;
23 wakaba 1.9 use overload '""' => sub { $_[0]->stringify },
24     fallback => 1;
25 wakaba 1.37 *REG = \%Message::Util::REG;
26 wakaba 1.1
27 wakaba 1.14 ## Initialize of this class -- called by constructors
28     %DEFAULT = (
29 wakaba 1.15 -_METHODS => [qw|header body content_type id|],
30 wakaba 1.17 -_MEMBERS => [qw|header body _cte|],
31 wakaba 1.18 ## entity_header -- Don't clone.
32 wakaba 1.15 -accept_coderange => '7bit', ## 7bit / 8bit / binary
33     -body_default_charset => 'iso-2022-int-1',
34 wakaba 1.18 -body_default_charset_input => 'iso-2022-int-1',
35     -body_default_media_type => 'text',
36     -body_default_media_subtype => 'plain',
37 wakaba 1.17 -cte_default => '7bit',
38 wakaba 1.33 -fill_missing_fields => 1,
39     #add_ua => 1,
40     #fill_date => 1,
41     -fill_date_name => 'date',
42     -fill_destination => 0,
43     #fill_destination_ns
44     #fill_destination_resent_ns
45     #fill_from_ns
46     -fill_md5 => 0,
47     -fill_md5_name => 'md5',
48     #fill_msgid => 1,
49     -fill_msgid_name => 'message-id',
50     #fill_sender_ns
51     -fill_source => 1,
52     -recalc_md5 => 1,
53 wakaba 1.19 -force_mime_entity => 0,
54 wakaba 1.15 -format => 'mail-rfc2822',
55 wakaba 1.28 -guess_media_type => 1,
56 wakaba 1.30 #internal_charset_name
57 wakaba 1.22 -header_default_charset => 'iso-2022-int-1',
58     -header_default_charset_input => 'iso-2022-int-1',
59 wakaba 1.15 -linebreak_strict => 0, ## BUG: not work perfectly
60 wakaba 1.37 -output_magic_line => 1,
61 wakaba 1.15 -parse_all => 0,
62 wakaba 1.37 -remove_post_newline => 0,
63     -remove_pre_newline => 0,
64 wakaba 1.17 -text_coderange => 'binary',
65     ## '8bit' (MIME text/*) / 'binary' (HTTP text/*)
66 wakaba 1.8 #ua_field_name => 'user-agent',
67 wakaba 1.21 -ua_use_Config => 1,
68     -ua_use_Win32 => 1,
69 wakaba 1.15 -uri_mailto_safe_level => 4,
70 wakaba 1.37 -use_magic_line => 1,
71 wakaba 1.14 );
72     sub _init ($;%) {
73     my $self = shift;
74     my %options = @_;
75 wakaba 1.15 $self->{option} = {};
76     my $o = Message::Util::make_clone (\%DEFAULT);
77     for my $name (keys %$o) {
78     if (substr ($name, 0, 1) eq '-') {
79     $self->{option}->{substr ($name, 1)} = $$o{$name};
80     }
81     }
82 wakaba 1.14
83 wakaba 1.8 my @new_fields = ();
84     for my $name (keys %options) {
85     if (substr ($name, 0, 1) eq '-') {
86     $self->{option}->{substr ($name, 1)} = $options{$name};
87 wakaba 1.18 } elsif ($name eq 'entity_header') {
88     $self->{entity_header} = $options{entity_header};
89 wakaba 1.8 } else {
90 wakaba 1.18 push @new_fields, ($name => $options{$name});
91 wakaba 1.8 }
92     }
93 wakaba 1.18
94 wakaba 1.8 my $format = $self->{option}->{format};
95 wakaba 1.37 my $ns822 = $Message::Header::NS_phname2uri{'x-rfc822'};
96     my $nshttp = $Message::Header::NS_phname2uri{'x-http'};
97 wakaba 1.14 if ($format =~ /http/) {
98 wakaba 1.37 $self->{option}->{fill_date_ns} = $nshttp unless defined $options{-fill_date_ns};
99     $self->{option}->{fill_from_ns} = $nshttp unless defined $options{-fill_from_ns};
100     $self->{option}->{fill_ua_ns} = $nshttp unless defined $options{-fill_ua_ns};
101     $self->{option}->{fill_source} = 0 unless defined $options{-fill_source};
102 wakaba 1.15 $self->{option}->{accept_coderange} = 'binary';
103 wakaba 1.17 $self->{option}->{text_coderange} = 'binary';
104     $self->{option}->{cte_default} = 'binary';
105 wakaba 1.14 } else {
106 wakaba 1.33 if ($format =~ /mail-rfc822|mail-rfc2822/) {
107     $self->{option}->{fill_destination} = 1;
108     }
109 wakaba 1.37 $self->{option}->{fill_date_ns} = $ns822 unless defined $options{-fill_date_ns};
110     $self->{option}->{fill_from_ns} = $ns822 unless defined $options{-fill_from_ns};
111     $self->{option}->{fill_ua_ns} = $ns822 unless defined $options{-fill_ua_ns};
112 wakaba 1.17 $self->{option}->{text_coderange} = '8bit';
113 wakaba 1.15 if ($format =~ /news-usefor|smtp-8bitmime/) {
114     $self->{option}->{accept_coderange} = '8bit';
115     } else {
116     $self->{option}->{accept_coderange} = '7bit';
117     }
118 wakaba 1.14 }
119 wakaba 1.37 for (qw/fill_msgid_ns fill_msgid_from fill_mimever_ns fill_destination_ns fill_sender_ns/) {
120     $self->{option}->{$_} = $ns822;
121 wakaba 1.33 }
122     $self->{option}->{fill_destination_resent_ns} = $Message::Header::NS_phname2uri{'x-rfc822-resent'};
123 wakaba 1.8 unless (defined $self->{option}->{fill_date}) {
124 wakaba 1.18 $self->{option}->{fill_date} = $format !~ /mime-entity|cgi|uri-url-mailto/;
125 wakaba 1.8 }
126     unless (defined $self->{option}->{fill_msgid}) {
127 wakaba 1.18 $self->{option}->{fill_msgid} = $format !~ /mime-entity|http|uri-url-mailto/;
128 wakaba 1.8 }
129 wakaba 1.15 unless (defined $self->{option}->{fill_ct}) {
130     $self->{option}->{fill_ct} = $format !~ /http/;
131     }
132 wakaba 1.8 unless (defined $self->{option}->{fill_mimever}) {
133 wakaba 1.18 $self->{option}->{fill_mimever} = $format !~ /http|mime-entity/;
134     }
135     unless (defined $self->{option}->{add_ua}) {
136     $self->{option}->{add_ua} = $format !~ /mime-entity/;
137 wakaba 1.8 }
138 wakaba 1.22 unless ($self->{option}->{fill_ua_name}) {
139 wakaba 1.14 $self->{option}->{fill_ua_name} = $format =~ /response|cgi|uri-url-mailto/?
140 wakaba 1.8 'server': 'user-agent';
141     }
142 wakaba 1.37 unless (defined $options{-output_magic_line}) {
143     $self->{option}->{output_magic_line} = 0
144     if $format =~ /mail|news|mime/;
145     }
146 wakaba 1.8 @new_fields;
147     }
148    
149     =head1 CONSTRUCTORS
150    
151     The following methods construct new C<Message::Entity> objects:
152 wakaba 1.3
153 wakaba 1.8 =over 4
154    
155 wakaba 1.9 =item Message::Entity->new ([%initial-fields/options])
156 wakaba 1.1
157 wakaba 1.9 Constructs a new C<Message::Entity> object. You might pass some initial
158     C<field-name>-C<field-body> pairs and/or options as parameters to the constructor.
159    
160     Example:
161    
162     $msg = new Message::Entity
163     Content_Type => 'text/html',
164     X_URI => '<http://www.foo.example/>',
165     -format => 'mail-rfc2822' ## not to be header field
166     ;
167 wakaba 1.1
168     =cut
169    
170     sub new ($;%) {
171     my $class = shift;
172 wakaba 1.8 my $self = bless {}, $class;
173     my %new_field = $self->_init (@_);
174 wakaba 1.22 if (defined $new_field{body}) {
175 wakaba 1.8 $self->{body} = $new_field{body}; $new_field{body} = undef;
176 wakaba 1.18 $self->{body} = $self->_parse_value ([$self->content_type] => $self->{body})
177 wakaba 1.8 if $self->{option}->{parse_all};
178     }
179 wakaba 1.14 $self->{header} = new Message::Header
180     -format => $self->{option}->{format},
181 wakaba 1.22 -header_default_charset => $self->{option}->{header_default_charset},
182     -header_default_charset_input => $self->{option}->{header_default_charset_input},
183 wakaba 1.8 -parse_all => $self->{option}->{parse_all}, %new_field;
184 wakaba 1.1 $self;
185     }
186    
187 wakaba 1.9 =item Message::Entity->parse ($message, [%options])
188 wakaba 1.1
189 wakaba 1.9 Parses given C<message> (a message entity) and constructs a new C<Message::Entity>
190     object. You might pass some additional C<field-name>-C<field-body> pairs
191     or/and initial options as parameters to the constructor.
192 wakaba 1.8
193 wakaba 1.1 =cut
194    
195     sub parse ($$;%) {
196     my $class = shift;
197     my $message = shift;
198 wakaba 1.8 my $self = bless {}, $class;
199     my %new_field = $self->_init (@_);
200 wakaba 1.20 my $nl = "\x0D\x0A";
201 wakaba 1.25 unless ($self->{option}->{linebreak_strict}) {
202 wakaba 1.23 $nl = Message::Util::decide_newline ($message);
203 wakaba 1.20 }
204 wakaba 1.37 my ($hdr, $body);
205     $message =~ s/^(?:$nl)+//s if $self->{option}->{remove_pre_newline};
206     $message =~ s/(?:$nl)+$/$nl/s if $self->{option}->{remove_post_newline};
207     if ($self->{option}->{use_magic_line}) {
208     ## TODO: Reset format option?
209     if ($message =~ s/>?From (.+?)$nl//gs) { ## Mail from line
210     $new_field{'x-rfc822-mail-from'} = $1;
211     } elsif ($message =~ s#^($REG{http_token})\x20($REG{S_uri})\x20($REG{http_token})/([0-9]+)\.([0-9]+)$nl##gs) {
212     ## HTTP Request
213     ($self->{http_method}, $self->{http_request_uri},
214     $self->{http_protocol_name}, $self->{http_protocol_version})
215     = ($1, $2, uc $3, pack ('U2', $4, $5));
216     } elsif ($message =~ s#^($REG{http_token})/([0-9]+)\.([0-9]+)\x20([0-9][0-9][0-9]\x20.*?)$nl##gs) {
217     ## HTTP Response
218     ($self->{http_protocol_name}, $self->{http_protocol_version})
219     = (uc $1, pack ('U2', $2, $3));
220     $new_field{'x-http-status'} = $4;
221     } elsif ($message =~ s#^($REG{http_token})\x20($REG{S_uri})$nl##gs) {
222     ## HTTP/0.9 simple-request
223     ($self->{http_method}, $self->{http_request_uri},
224     $self->{http_protocol_name}, $self->{http_protocol_version})
225     = ($1, $2, 'HTTP', v0.9);
226     $message = $nl . $message; ## Has no header fields
227 wakaba 1.1 }
228     }
229 wakaba 1.37 if ($message !~ s/^$nl//s) {
230     ($hdr, $body) = split /$nl$nl/, $message, 2;
231     } else {
232     $hdr = ''; $body = $message;
233     $body =~ s/^$nl//s;
234     }
235 wakaba 1.8 $new_field{body} = undef if $new_field{body};
236 wakaba 1.37 ## Is this implemention good?
237     $self->{header} = parse Message::Header $hdr,
238 wakaba 1.22 -header_default_charset => $self->{option}->{header_default_charset},
239     -header_default_charset_input => $self->{option}->{header_default_charset_input},
240 wakaba 1.8 -parse_all => $self->{option}->{parse_all},
241 wakaba 1.37 -format => $self->{option}->{format},
242     %new_field; ## Additional header fields
243    
244     $self->{body} = $body;
245     $self->{body} = $self->_parse_value ([ $self->content_type ] => $self->{body})
246 wakaba 1.8 if $self->{option}->{parse_all};
247 wakaba 1.1 $self;
248     }
249    
250 wakaba 1.9 =back
251    
252 wakaba 1.8 =head1 METHODS
253    
254 wakaba 1.1 =head2 $self->header ([$new_header])
255    
256     Returns Message::Header unless $new_header.
257     Set $new_header instead of current C<header>.
258     If !ref $new_header, Message::Header->parse is automatically
259     called.
260    
261     =cut
262    
263 wakaba 1.9 ## TODO: to be compatible with HTTP::Message
264 wakaba 1.1 sub header ($;$) {
265     my $self = shift;
266     my $new_header = shift;
267     if (ref $new_header) {
268     $self->{header} = $new_header;
269     } elsif ($new_header) {
270 wakaba 1.4 $self->{header} = Message::Header->parse ($new_header,
271 wakaba 1.22 -header_default_charset => $self->{option}->{header_default_charset},
272     -header_default_charset_input => $self->{option}->{header_default_charset_input},
273 wakaba 1.8 -parse_all => $self->{option}->{parse_all},
274     -format => $self->{option}->{format});
275 wakaba 1.1 }
276 wakaba 1.14 unless (ref $self->{header} || length $self->{header}) {
277     $self->{header} = new Message::Header (
278 wakaba 1.22 -header_default_charset => $self->{option}->{header_default_charset},
279     -header_default_charset_input => $self->{option}->{header_default_charset_input},
280 wakaba 1.14 -parse_all => $self->{option}->{parse_all},
281     -format => $self->{option}->{format});
282 wakaba 1.2 }
283 wakaba 1.1 $self->{header};
284     }
285    
286     =head2 $self->body ([$new_body])
287    
288     Returns C<body> as string unless $new_body.
289     Set $new_body instead of current C<body>.
290    
291     =cut
292    
293     sub body ($;$) {
294     my $self = shift;
295     my $new_body = shift;
296     if ($new_body) {
297     $self->{body} = $new_body;
298     }
299 wakaba 1.18 $self->{body} = $self->_parse_value ([$self->content_type] => $self->{body})
300 wakaba 1.3 unless ref $self->{body};
301 wakaba 1.1 $self->{body};
302     }
303    
304 wakaba 1.18 ## [SG]et its entity header. This method is or can be used
305     ## when Message::Entity is used as a body (such as message/rfc822).
306     sub entity_header ($;$) {
307     my $self = shift;
308     my $new_header = shift;
309     if (ref $new_header) {
310     $self->{entity_header} = $new_header;
311     }
312     $self->{entity_header};
313     }
314    
315 wakaba 1.24 ## Note: If you once parse body (including parse_all => 1 option),
316     ## it might make validation failed.
317     sub md5_check ($) {
318     my $self = shift;
319     my $md5f = $self->{header}->field ('content-md5', -new_item_unless_exist => 0);
320     my $md5; $md5 = $md5f->value if ref $md5f;
321     unless ($md5) {
322     Carp::carp "md5_check: MD5 checksum not found";
323     return undef;
324     }
325     my $MD5;
326     eval q{
327 wakaba 1.34 require Digest::MD5;
328     $MD5 = ($self->Message::MIME::Encoding::encode_base64 (Digest::MD5::md5 ($self->{body})))[0];
329     $MD5 =~ tr/\x09\x0A\x0D\x20//d;
330     1} or Carp::croak $@;
331 wakaba 1.24 return $MD5 eq $md5? 1 : 0;
332     }
333    
334 wakaba 1.14 ## $self->_parse_value ($type, $value);
335     sub _parse_value ($$$) {
336 wakaba 1.3 my $self = shift;
337 wakaba 1.18 my ($mt,$mst) = @{ shift(@_) };
338 wakaba 1.14 my $value = shift;
339     return $value if ref $value;
340    
341     ## decode
342     $value = $self->_decode_body ($value);
343    
344 wakaba 1.18 my $mt_def = $Message::MIME::MediaType::type{$mt}->{$mst};
345     $mt_def = $Message::MIME::MediaType::type{$mt}->{'/default'} unless ref $mt_def;
346     $mt_def = $Message::MIME::MediaType::type{'/default'}->{'/default'}
347     unless ref $mt_def;
348     my $handler = $mt_def->{handler}
349     || $Message::MIME::MediaType::type{$mt}->{'/default'}->{handler}
350     || $Message::MIME::MediaType::type{'/default'}->{'/default'}->{handler};
351     ## Ummmmmm....
352     if (ref $handler eq 'CODE') {
353     $handler = &$handler ($self, $mt, $mst);
354     }
355     my $vtype = $handler->[0];
356     my %vopt = (
357     -format => $self->{option}->{format},
358 wakaba 1.25 -linebreak_strict => $self->{option}->{linebreak_strict},
359 wakaba 1.18 -media_type => $mt,
360     -media_subtype => $mst,
361     -parse_all => $self->{option}->{parse_all},
362     -body_default_charset => $self->{option}->{body_default_charset},
363     -body_default_charset_input => $self->{option}->{body_default_charset_input},
364 wakaba 1.30 -internal_charset_name => $self->{option}->{internal_charset_name},
365 wakaba 1.18 entity_header => $self->{header},
366     );
367     ## Media type specified option/parameters
368     if (ref $handler->[1] eq 'HASH') {
369     for (keys %{$handler->[1]}) {
370     $vopt{$_} = ${$handler->[1]}{$_};
371     }
372     }
373     ## Inherited options
374     if (ref $handler->[2] eq 'ARRAY') {
375     for (@{$handler->[2]}) {
376     $vopt{'-'.$_} = $self->{option}->{$_};
377     }
378     }
379    
380 wakaba 1.14 if ($vtype eq ':none:') {
381     return $value;
382     } elsif (defined $value) {
383     eval "require $vtype" or Carp::croak qq{<parse>: $vtype: Can't load package: $@};
384 wakaba 1.18 return $vtype->parse ($value, %vopt);
385 wakaba 1.3 } else {
386 wakaba 1.14 eval "require $vtype" or Carp::croak qq{<parse>: $vtype: Can't load package: $@};
387 wakaba 1.18 return $vtype->new (%vopt);
388 wakaba 1.3 }
389     }
390    
391 wakaba 1.14 sub _decode_body ($$) {
392     my $self = shift;
393     my $value = shift;
394     ## MIME CTE
395 wakaba 1.22 my $cte = $self->{_cte} || '';
396 wakaba 1.14 my $ctef = $self->header->field ('content-transfer-encoding',
397     -new_item_unless_exist => 0);
398     $cte = $ctef->value if ref $ctef;
399 wakaba 1.15 my $f = $Message::MIME::Encoding::DECODER{$cte};
400 wakaba 1.14 if (ref $f) {
401     ($value, $cte) = &$f ($self, $value);
402     }
403     $self->{_cte} = $cte;
404     $value;
405     }
406    
407 wakaba 1.15 sub _encode_body ($$\%) {
408 wakaba 1.14 my $self = shift;
409     my $value = shift;
410 wakaba 1.15 my $option = shift;
411 wakaba 1.14 ## MIME CTE
412 wakaba 1.17 my $current_cte = $self->{_cte} || 'binary';
413     my $ctef = $self->{header}->field ('content-transfer-encoding',
414 wakaba 1.14 -new_item_unless_exist => 0);
415 wakaba 1.15 my $cte = ''; $cte = lc $ctef->value if ref $ctef;
416 wakaba 1.16 my %enoption;
417 wakaba 1.15 ## Get media type of entity body and its accept CTE list
418     my ($mt,$mst) = $self->content_type;
419     my $mt_def = $Message::MIME::MediaType::type{$mt}->{$mst};
420     $mt_def = $Message::MIME::MediaType::type{$mt}->{'/default'}
421 wakaba 1.18 unless ref $mt_def;
422 wakaba 1.15 $mt_def = $Message::MIME::MediaType::type{'/default'}->{'/default'}
423     unless ref $mt_def;
424 wakaba 1.16 $enoption{mt_is_text} = 1
425     if $mt eq 'text' || $mt eq 'multipart' || $mt eq 'message';
426 wakaba 1.23 $enoption{mt_is_text} = 1 if $mt_def->{text_content};
427 wakaba 1.16 my ($charset, $charset_def) = '';
428     if ($mt_def->{mime_charset}) {
429     ## If CT is able to have its charset parameter,
430 wakaba 1.17 my $ct = $self->{header}->field ('content-type',
431 wakaba 1.16 -new_item_unless_exist => 0);
432     $charset = $ct->parameter ('charset') if ref $ct;
433     if ($charset) {
434     $charset_def = $Message::MIME::Charset::CHARSET{$charset};
435     } else {
436     $charset_def = $Message::MIME::Charset::CHARSET{'*default'};
437 wakaba 1.31 ## Note: 'encoding_after_encode' option's value is hardcoded.
438 wakaba 1.16 }
439 wakaba 1.18 } else { ## Don't have mime style "charset" parameter
440     $charset_def = {mime_text => 1};
441 wakaba 1.16 }
442     $charset_def = {} unless ref $charset_def; ## dummy
443 wakaba 1.31 #if ($charset_def->{mime_text} != 1) { ## See also Note above
444     if (Message::MIME::Charset::is_mime_text ($charset || '*default') != 1) {
445 wakaba 1.18 $enoption{mt_is_text} = 0 if $mt eq 'text';
446 wakaba 1.17 my $ct = $self->{header}->field ('content-type');
447     $ct->not_mime_text ($option->{text_coderange} eq 'binary'? 0:1);
448     }
449 wakaba 1.15 ## If accept CTE list is defined,
450 wakaba 1.16 for my $def ($charset_def, $mt_def) {
451     if (ref $def->{accept_cte} eq 'ARRAY') {
452     my $f = 1; for (@{$def->{accept_cte}}) {
453     if ($cte eq $_) {$f = 0; last}
454     }
455     if ($f) { ## If CTE is not accepted,
456     $cte = $def->{accept_cte}->[0];
457     }
458 wakaba 1.15 }
459     }
460     if ($current_cte eq 'binary' || ($current_cte && $current_cte ne $cte)) {
461     my $de = $Message::MIME::Encoding::DECODER{$current_cte};
462     my $en = $Message::MIME::Encoding::ENCODER{$cte || 'binary'};
463     if (ref $de && ref $en) {
464     my ($e, $decoded);
465     ($decoded, $e) = &$de ($self, $value);
466     ## Check transparent coderange
467 wakaba 1.16 my $cr = $self->Message::MIME::Encoding::decide_coderange
468     ($decoded, \%enoption);
469 wakaba 1.15 if ($option->{accept_coderange} eq '8bit') {
470     if ($cr eq 'binary') {
471 wakaba 1.16 $cte = $charset_def->{cte_7bit_preferred}
472     || $mt_def->{cte_7bit_preferred} || 'base64';
473 wakaba 1.15 $en = $Message::MIME::Encoding::ENCODER{$cte};
474     }
475     } elsif ($option->{accept_coderange} eq '7bit') {
476     if ($cr eq 'binary' || $cr eq '8bit') {
477 wakaba 1.16 $cte = $charset_def->{cte_7bit_preferred}
478     || $mt_def->{cte_7bit_preferred} || 'base64';
479 wakaba 1.15 $en = $Message::MIME::Encoding::ENCODER{$cte};
480 wakaba 1.18 if ($mt eq 'message') {
481     my $ct = $self->{header}->field ('content-type');
482     $ct->not_mime_text ($option->{text_coderange} eq 'binary'? 0:1);
483     }
484 wakaba 1.15 }
485     }
486     if ($e eq 'binary') {
487 wakaba 1.16 ($value, $e) = &$en ($self, $decoded, \%enoption);
488 wakaba 1.17 $e = '' if ($e eq $option->{cte_default});
489     $e = '' if $e eq '7bit'
490     && ( $option->{cte_default} eq '8bit'
491     || $option->{cte_default} eq 'binary');
492     $e = '' if $e eq '8bit' && $option->{cte_default} eq 'binary';
493     if ($e) {
494     $ctef = $self->{header}->field ('content-transfer-encoding')
495 wakaba 1.15 unless ref $ctef;
496     $ctef->value ($e);
497 wakaba 1.17 } elsif (ref $ctef) {
498     $ctef->value ('');
499     }
500 wakaba 1.15 } else {
501 wakaba 1.17 $ctef = $self->{header}->field ('content-transfer-encoding')
502 wakaba 1.15 unless ref $ctef;
503     $ctef->value ($current_cte);
504     }
505 wakaba 1.14 } else { ## Can't encode by given CTE
506 wakaba 1.17 $ctef = $self->{header}->field ('content-transfer-encoding')
507 wakaba 1.15 unless ref $ctef;
508 wakaba 1.14 $ctef->value ($current_cte);
509     }
510     }
511 wakaba 1.17 if (ref $ctef && $ctef->value eq '') {
512     $self->{header}->delete ('content-transfer-encoding');
513     }
514 wakaba 1.14 $value;
515     }
516    
517 wakaba 1.1 =head2 $self->stringify ([%option])
518    
519     Returns the C<message> as a string.
520    
521     =cut
522    
523     sub stringify ($;%) {
524     my $self = shift;
525 wakaba 1.8 my %params = @_;
526     my %option = %{$self->{option}};
527     for (grep {/^-/} keys %params) {$option{substr ($_, 1)} = $params{$_}}
528 wakaba 1.18 my ($header, $body, $body0);
529 wakaba 1.14 if (ref $self->{body}) {
530 wakaba 1.18 $self->{body}->entity_header ($self->{header});
531 wakaba 1.27 $body0 = $self->{body}->stringify (-parent_format => $option{format},
532 wakaba 1.14 -linebreak_strict => $option{linebreak_strict});
533     } else {
534 wakaba 1.18 $body0 = $self->{body};
535 wakaba 1.14 }
536 wakaba 1.18 $body = $self->_encode_body ($body0, \%option);
537 wakaba 1.14 if (ref $self->{header}) {
538 wakaba 1.15 my $ns_content = $Message::Header::NS_phname2uri{content};
539 wakaba 1.33 my $filler;
540     $filler = sub {
541     my ($hdr, $exist, $hdr_option) = @_;
542     ## Date: (RFC 822, HTTP)
543     if ($option{fill_date}
544 wakaba 1.34 && !$exist->{$option{fill_date_name}.':'.$option{fill_date_ns}}) {
545     $hdr->field
546 wakaba 1.33 ($option{fill_date_name}, -ns => $option{fill_date_ns})->unix_time (time);
547     }
548     ## Message-ID: (RFC 822)
549     if ($option{fill_msgid}
550 wakaba 1.34 && !$exist->{$option{fill_msgid_name}.':'.$option{fill_msgid_ns}}) {
551     my $from = $hdr->field
552 wakaba 1.33 ('from', -ns => $option{fill_msgid_from_ns}, -new_item_unless_exist => 0);
553     $from = $from->addr_spec if ref $from;
554 wakaba 1.34 $hdr->field ($option{fill_msgid_name}, -ns => $option{fill_msgid_ns})
555     ->generate (addr_spec => $from) if $from;
556 wakaba 1.33 } # fill_msgid
557     ## To:, CC:, BCC:, Resent-To:, Resent-Cc:, Resent-Bcc: (RFC 822)
558     if ($option{fill_destination}) {
559 wakaba 1.34 if ( !$exist->{ 'to:'.$option{fill_destination_ns} }
560     && !$exist->{ 'cc:'.$option{fill_destination_ns} }
561     && !$exist->{ 'bcc:'.$option{fill_destination_ns} }
562     && !$exist->{ 'to:'.$option{fill_destination_resent_ns} }
563     && !$exist->{ 'cc:'.$option{fill_destination_resent_ns} }
564     && !$exist->{ 'bcc:'.$option{fill_destination_resent_ns} } ) {
565 wakaba 1.33 $hdr->add (bcc => '');
566     }
567     }
568     ## From:, Sender:
569     if ($option{fill_source}) {
570     ## From:
571 wakaba 1.34 if (!$exist->{ 'from:'.$option{fill_from_ns} }) {
572 wakaba 1.33 $hdr->add (from => 'Unknown source <[email protected]>',
573     -ns => $option{fill_from_ns});
574     ## From: exists, Sender: not exist
575 wakaba 1.34 } elsif (!$exist->{ 'sender:'.$option{fill_sender_ns} }) {
576 wakaba 1.33 my $from = $hdr->field ('from', -ns => $option{fill_from_ns});
577     if ($from->count > 1) {
578     $hdr->field ('sender', -ns => $option{fill_sender_ns})
579     ->add ($from->item (0, -by => 'index'));
580     }
581     }
582     }
583     ## Content-MD5:
584 wakaba 1.34 if (($option{fill_md5} && !$exist->{ $option{fill_md5_name} .':'. $ns_content})
585     || ($option{recalc_md5} && $exist->{ $option{fill_md5_name} .':'. $ns_content})) {
586 wakaba 1.33 my $md5;
587     eval q{
588 wakaba 1.34 require Digest::MD5;
589     $md5 = ($self->Message::MIME::Encoding::encode_base64 (Digest::MD5::md5 ($body0)))[0];
590 wakaba 1.33 $md5 =~ tr/\x09\x0A\x0D\x20//d;
591 wakaba 1.34 1} or Carp::carp $@;
592 wakaba 1.33 if ($md5) {
593 wakaba 1.34 my $md5f = $hdr->field ($option{fill_md5_name}, -ns => $ns_content);
594 wakaba 1.33 $md5f->value ($md5);
595     }
596 wakaba 1.24 }
597 wakaba 1.33 my $ismime = 0;
598 wakaba 1.34 for (keys %$exist) {if (/:$ns_content$/) { $ismime = 1; last }}
599 wakaba 1.33 unless ($ismime) {
600 wakaba 1.34 $ismime = 1 if $option{force_mime_entity}
601     || $option{fill_md5}
602     || $option{body_default_media_type} ne 'text'
603     || $option{body_default_media_subtype} ne 'plain';
604 wakaba 1.15 }
605 wakaba 1.33 if ($ismime) {
606     ## Content-Type: (MIME, HTTP)
607 wakaba 1.34 if ($option{fill_ct} && !$exist->{'type:'.$ns_content}) {
608     my $ct = $hdr->field ('type', -ns => $ns_content);
609 wakaba 1.33 $ct->media_type ($option{body_default_media_type}.'/'
610     .$option{body_default_media_subtype});
611     $ct->replace (Message::MIME::Charset::name_minimumize ($option{body_default_charset} => $body0));
612     }
613     ## MIME-Version: (MIME)
614     if ($option{fill_mimever}
615 wakaba 1.34 && !$exist->{'mime-version:'.$option{fill_mimever_ns}}) {
616     ## BUG: doesn't support rfc1049, HTTP (ie. non-MIME) content-*: fields
617     $hdr->add ('mime-version' => '1.0',
618 wakaba 1.33 -parse => 0, -ns => $option{fill_mimever_ns});
619     }
620     } # $ismime
621     ## User-Agent: (USEFOR, HTTP)
622     if ($option{add_ua}) {
623 wakaba 1.34 $hdr->field ($option{fill_ua_name})->add_our_name (
624 wakaba 1.33 -use_Config => $option{ua_use_Config},
625     -use_Win32 => $option{ua_use_Win32},
626 wakaba 1.37 -date => q$Date: 2002/08/01 09:20:34 $,
627 wakaba 1.33 );
628 wakaba 1.8 }
629 wakaba 1.33 } if $option{fill_missing_fields};
630    
631     if ($option{format} =~ /uri-url-mailto/
632     && $self->{header}->field_exist ('type', -ns => $ns_content)
633 wakaba 1.12 && $option{uri_mailto_safe_level} > 1) {
634 wakaba 1.33 $self->{header}->field ('type', -ns => $ns_content)->media_type ('text/plain');
635 wakaba 1.12 }
636 wakaba 1.33 $header = $self->{header}->stringify (
637     -format => $option{format},
638     -linebreak_strict => $option{linebreak_strict},
639     -uri_mailto_safe_level => $option{uri_mailto_safe_level},
640     ($filler? (-hook_stringify_fill_fields => $filler) :()),
641     );
642 wakaba 1.7 } else {
643     $header = $self->{header};
644 wakaba 1.12 unless ($option{linebreak_strict}) {
645     ## bare \x0D and bare \x0A are unsafe
646     $header =~ s/\x0D(?=[^\x09\x0A\x20])/\x0D\x20/g;
647     $header =~ s/\x0A(?=[^\x09\x20])/\x0A\x20/g;
648     }
649 wakaba 1.7 }
650 wakaba 1.12 if ($option{format} =~ /uri-url-mailto/) {
651 wakaba 1.14 if ($option{format} =~ /rfc1738/) {
652     my $to = $self->{header}->stringify (-format => $option{format},
653     -uri_mailto_safe_level => $option{uri_mailto_safe_level});
654     $to? 'mailto:'.$to: '';
655     } else {
656     my $f = $option{format}; $f =~ s/-mailto/-mailto-to/;
657     my $to = $self->{header}->stringify (-format => $f,
658     -uri_mailto_safe_level => $option{uri_mailto_safe_level});
659     $body =~ s/([^:@+\$A-Za-z0-9\-_.!~*])/sprintf('%%%02X', ord $1)/ge;
660     if (length $body) {
661     $header .= '&' if $header;
662     $header .= 'body='.$body;
663     }
664     $header = '?'.$header if $header;
665     $to||$header? 'mailto:'.$to.$header: '';
666 wakaba 1.12 }
667     } else {
668 wakaba 1.37 ## Magic line (<- named by the author of this module:-)
669     my $mline;
670     if ($option{use_magic_line} && $option{output_magic_line}) {
671     if ($option{format} =~ /mail|news/ && ref $self->{header}) {
672     my $mfrom = $self->{header}->field ('mail-from', -new_item_unless_exist=>0);
673     $mline = sprintf 'From %s', $mfrom->value if ref $mfrom;
674     } elsif ($option{format} =~ /http.+?request/) {
675     $mline = sprintf '%s %s %s/%vd', $self->{http_method} || 'GET',
676     $self->{http_request_uri} || '/', $self->{http_protocol_name} || 'HTTP',
677     $self->{http_protocol_version} || v1.0;
678     } elsif ($option{format} =~ /http.+?response/ && ref $self->{header}
679     && $option{format} !~ /cgi/) {
680     my $s = $self->{header}->field ('x-http-status');
681     $mline = sprintf '%s/%vd %s', $self->{http_protocol_name} || 'HTTP',
682     $self->{http_protocol_version} || v1.0, $s->value || '200 OK';
683     }
684     }
685     $mline .= "\x0D\x0A" if $mline;
686     $mline = '' unless $mline;
687    
688 wakaba 1.15 $header .= "\x0D\x0A" if $header && $header !~ /\x0D\x0A$/;
689 wakaba 1.37 $mline.$header."\x0D\x0A".$body;
690 wakaba 1.12 }
691 wakaba 1.1 }
692 wakaba 1.8 *as_string = \&stringify;
693 wakaba 1.1
694    
695 wakaba 1.9 =head1 SHORTCUT METHOD FOR MESSAGE PROPERTIES
696    
697     =over 4
698    
699     =item $self->content_type ([%options])
700 wakaba 1.1
701 wakaba 1.9 Returns Internet media type of message body
702     (aka MIME type, content type). Only media type
703     (type/subtype pair) is returned, i.e. no parameter
704     is returned, if any. To get such value, or to set
705     new value, use C<field> method.
706 wakaba 1.1
707 wakaba 1.9 Default is C<text/plain>.
708 wakaba 1.3
709 wakaba 1.9 Example:
710 wakaba 1.3
711 wakaba 1.9 $msg->field ('Content-Type')->media_type ('text/html');
712     print $msg->content_type; ## text/html
713 wakaba 1.3
714     =cut
715    
716     sub content_type ($;%) {
717 wakaba 1.8 my $self = shift;
718 wakaba 1.15 my $ct = $self->{header}->field ('content-type', -new_item_unless_exist => 0);
719 wakaba 1.28 my ($mt, $mst);
720 wakaba 1.15 unless (ref $ct) {
721 wakaba 1.28 $mt = $self->{option}->{body_default_media_type};
722     $mst = $self->{option}->{body_default_media_subtype};
723     if ($mt ne 'text' || $mst ne 'plain') {
724 wakaba 1.18 $ct = $self->{header}->field ('content-type');
725 wakaba 1.28 $ct->media_type_major ($mt);
726     $ct->media_type_minor ($mst);
727     }
728 wakaba 1.37 if ($self->{option}->{guess_media_type} && $self->{body} && !ref $self->{body}
729     && $self->{option}->{format} =~ /mail|news/) {
730 wakaba 1.29 if ($self->{body} =~ /^-----BEGIN PGP SIGNED MESSAGE-----\x0D?$/m
731     && $self->{body} =~ /^-----BEGIN PGP SIGNATURE-----\x0D?$/m
732     && $self->{body} =~ /^-----END PGP SIGNATURE-----\x0D?$/m) {
733     $ct = $self->{header}->field ('content-type') unless ref $ct;
734     $mt = $ct->media_type_major ('text');
735     $mst = $ct->media_type_minor ('x-pgp-cleartext-signed');
736     } elsif ($self->{body} =~ /^-----BEGIN PGP [A-Z\x20]+-----\x0D?$/m
737     && $self->{body} =~ /^-----END PGP [A-Z\x20]+-----\x0D?$/m) {
738     $ct = $self->{header}->field ('content-type') unless ref $ct;
739     $mt = $ct->media_type_major ('application');
740     $mst = $ct->media_type_minor ('pgp');
741     $ct->parameter (format => 'text');
742     } elsif ($self->{body} =~ /^-+ start of forwarded message \(RFC 934 encapsulation\) -+\x0D?$/m) {
743     $ct = $self->{header}->field ('content-type') unless ref $ct;
744     $mt = $ct->media_type_major ('text');
745     $mst = $ct->media_type_minor ('x-message-rfc934');
746     } elsif ($self->{body} =~ /^-{70,70}\x0D?$/m
747     && $self->{body} =~ /^-{30,30}\x0D?$/m
748     && $self->{body} =~ /\x0D?\x0A-{30,30}\x0D?\x0A\x0D?\x0AEnd of.+?Digest.*?\x0D?\x0A\*+(?:\x0D?\x0A)*$/s) {
749     $ct = $self->{header}->field ('content-type') unless ref $ct;
750     $mt = $ct->media_type_major ('text');
751     $mst = $ct->media_type_minor ('x-message-rfc1153');
752     } elsif ($self->{body} =~ /^-----PRIVACY-ENHANCED MESSAGE BOUNDARY-----\x0D?$/m) {
753     $ct = $self->{header}->field ('content-type') unless ref $ct;
754     $mt = $ct->media_type_major ('text');
755     $mst = $ct->media_type_minor ('x-message-pem');
756 wakaba 1.37 } elsif ($self->{body} =~ /^#(?:HELO|EHLO)/mi
757     && $self->{body} =~ /^#MAIL FROM:/mi
758     && $self->{body} !~ /^[^#]/m) {
759     ## RFC 976 Batch SMTP (BSMTP) message
760     $ct = $self->{header}->field ('content-type') unless ref $ct;
761     $mt = $ct->media_type_major ('application');
762     $mst = $ct->media_type_minor ('x-batch-smtp');
763 wakaba 1.29 }
764 wakaba 1.28 }
765     } else {
766     ($mt, $mst) = ($ct->media_type_major, $ct->media_type_minor);
767     }
768     if ($self->{option}->{guess_media_type}) {
769     if ($mt eq 'text' && $mst eq 'plain') {
770     my $mls = $self->{header}->field ('x-mlserver', -new_item_unless_exist => 0);
771     if (ref $mls && $mls =~ /fml/) {
772     my $s = $self->{header}->field ('subject', -new_item_unless_exist => 0);
773     if (index ($s, 'RFC934(mh-burst)') >= 0) {
774     $ct = $self->{header}->field ('content-type') unless ref $ct;
775 wakaba 1.29 $mt = $ct->media_type_major ('text');
776     $mst = $ct->media_type_minor ('x-message-rfc934');
777     $ct->delete ('charset');
778     } elsif (index ($s, 'Digest (RFC1153)') >= 0) {
779     $ct = $self->{header}->field ('content-type') unless ref $ct;
780     $mt = $ct->media_type_major ('text');
781     $mst = $ct->media_type_minor ('x-message-rfc1153');
782 wakaba 1.28 $ct->delete ('charset');
783     }
784     }
785 wakaba 1.18 }
786 wakaba 1.15 }
787     if (wantarray) {
788 wakaba 1.28 ($mt, $mst);
789 wakaba 1.15 } else {
790     $ct->media_type;
791     }
792 wakaba 1.1 }
793 wakaba 1.15 *media_type = \&content_type;
794 wakaba 1.1
795 wakaba 1.9 =item $self->id
796    
797     Returns ID of message entity. If there are C<Message-ID:>
798     field, its value is returned. Unless, but there are
799     C<Content-ID:> field, it is returned. Without both of
800     fields, C<""> is returned.
801    
802     =cut
803    
804 wakaba 1.5 sub id ($) {
805     my $self = shift;
806     return scalar $self->{header}->field ('message-id')->id
807     if $self->{header}->field_exist ('message-id');
808 wakaba 1.9 return scalar $self->{header}->field ('content-id')->id
809     if $self->{header}->field_exist ('content-id');
810 wakaba 1.8 '';
811 wakaba 1.5 }
812    
813 wakaba 1.35 sub sender ($;%) {
814     my $self = shift;
815     my %params = @_;
816     my %option = %{$self->{option}};
817     $option{use_x_envelope_from} = 1; ## X-Envelope-From:
818     $option{use_normal} = 1; ## From:, Sender:
819     $option{use_resent} = 1; ## Resent-From:, Resent-Sender:
820     my $hdr = $self->{header};
821     if ($option{use_x_envelope_from} && $hdr->field_exist ('x-envelope-from')) {
822     return $hdr->field ('x-envelope-from')->addr_spec;
823     } elsif ($option{use_resent} && $hdr->field_exist ('resent-sender')) {
824     ## TODO: Resent block support
825     return $hdr->field ('resent-sender')->addr_spec;
826     } elsif ($option{use_resent} && $hdr->field_exist ('resent-from')) {
827     ## TODO: Resent block support
828     return $hdr->field ('resent-from')->addr_spec;
829     } elsif ($option{use_normal} && $hdr->field_exist ('sender')) {
830     return $hdr->field ('sender')->addr_spec;
831     } elsif ($option{use_normal} && $hdr->field_exist ('from')) {
832     return $hdr->field ('from')->addr_spec;
833     }
834     undef;
835     }
836    
837     sub destination ($;%) {
838     my $self = shift;
839     my %params = @_;
840     my %option = %{$self->{option}};
841     $option{use_x_envelope_to} = 1; ## X-Envelope-To:
842     $option{use_normal} = 1; ## To:, Cc:, Bcc:
843     $option{use_resent} = 1; ## Resent-To:, Resent-Cc:, Resent-Bcc:
844     for (grep {/^-/} keys %params) {$option{substr ($_, 1)} = $params{$_}}
845     my $hdr = $self->{header};
846     my @to;
847 wakaba 1.37 if ($option{use_x_envelope_to} && $hdr->field_exist ('x-rfc822-x-envelope-to')) {
848     @to = $hdr->field ('x-rfc822-x-envelope-to')->addr_spec;
849     } elsif ($option{use_resent} && $hdr->field_exist ('x-rfc822-resent-from')) {
850 wakaba 1.35 ## TODO: Resent block support
851 wakaba 1.37 @to = ($hdr->field ('x-rfc822-resent-to')->addr_spec,
852     $hdr->field ('x-rfc822-resent-cc')->addr_spec,
853     $hdr->field ('x-rfc822-resent-bcc')->addr_spec);
854 wakaba 1.35 } elsif ($option{use_normal}) {
855 wakaba 1.37 @to = ($hdr->field ('x-rfc822-to')->addr_spec,
856     $hdr->field ('x-rfc822-cc')->addr_spec,
857     $hdr->field ('x-rfc822-bcc')->addr_spec);
858 wakaba 1.35 }
859     @to;
860     }
861    
862 wakaba 1.36 sub list_name ($) {
863     my $self = shift;
864     my $hdr = $self->{header};
865     if ($hdr->field_exist ('list-id')) {
866     my $lname = $hdr->field ('list-id')->display_name;
867     return $lname if length $lname;
868     }
869     my $v = sub {
870     my $name = shift;
871     my $f = $hdr->field ($name, -new_item_unless_exist => 0);
872     return $f->value if ref $f;
873     undef;
874     };
875     ## BUG: list-name "0" is not supported.
876     my $lname = &$v ('x-ml-name') || &$v ('x-mailing-list-name')
877     || &$v ('x-mailinglist-name') || &$v ('ml-name');
878     return $lname if length $lname;
879     if ($hdr->field_exist ('x-sequence')) {
880     if ($hdr->field ('x-sequence')->value =~ /^(\S+)\s+\d+$/) {
881     return $1;
882     }
883     }
884     if ($hdr->field_exist ('subject')) {
885 wakaba 1.37 my $s = $hdr->field ('subject');
886     return $s->list_name if $s->method_available ('list_name');
887 wakaba 1.36 }
888     undef;
889     }
890    
891     sub list_count ($) {
892     my $self = shift;
893     my $hdr = $self->{header};
894     my $v = sub {
895     my $name = shift;
896     my $f = $hdr->field ($name, -new_item_unless_exist => 0);
897     return $f->value if ref $f;
898     undef;
899     };
900     ## BUG: list-count 0 is not supported.
901     my $lc = &$v ('x-mail-count') || &$v ('x-ml-count') || &$v ('x-mailinglist-id')
902     || &$v ('mail-count') || &$v ('x-article-no') || &$v ('x-ml-counter')
903     || &$v ('x-ml-id') || &$v ('x-ml-sequence') || &$v ('x-serial-no')
904     || &$v ('x-seqno');
905     return $lc if $lc;
906     if ($hdr->field_exist ('x-sequence')) {
907     if ($hdr->field ('x-sequence')->value =~ /^\S+\s+(\d+)$/) {
908     return $1;
909     }
910     }
911     if ($hdr->field_exist ('subject')) {
912 wakaba 1.37 my $s = $hdr->field ('subject');
913     return $s->list_count if $s->method_available ('list_count');
914 wakaba 1.36 }
915     undef;
916     }
917    
918 wakaba 1.9 =back
919    
920     =head1 MISC. METHODS
921    
922     =over 4
923    
924     =item $self->option ( $option-name / $option-name, $option-value, ...)
925    
926     If @_ == 1, returns option value. Else...
927    
928     Set option value. You can pass multiple option name-value pair
929     as parameter. Example:
930    
931     $msg->option (format => 'mail-rfc822',
932     capitalize => 0);
933     print $msg->option ('format'); ## mail-rfc822
934    
935     =cut
936    
937     sub option ($@) {
938     my $self = shift;
939     if (@_ == 1) {
940     return $self->{option}->{ $_[0] };
941     }
942 wakaba 1.18 my %option = @_;
943 wakaba 1.9 while (my ($name, $value) = splice (@_, 0, 2)) {
944     $self->{option}->{$name} = $value;
945     }
946 wakaba 1.32 if ($option{-recursive} && ($self->content_type)[0] ne 'message') {
947 wakaba 1.18 $self->{header}->option (%option);
948     $self->{body}->option (%option) if ref $self->{body};
949     }
950 wakaba 1.9 }
951    
952     =item $self->clone ()
953 wakaba 1.8
954     Returns a copy of Message::Entity object.
955    
956     =cut
957    
958     sub clone ($) {
959     my $self = shift;
960     my $clone = new Message::Entity;
961 wakaba 1.14 $clone->{option} = Message::Util::make_clone ($self->{option});
962     for (@{$self->{option}->{_MEMBERS}}) {
963     $clone->{$_} = Message::Util::make_clone ($self->{$_});
964 wakaba 1.8 }
965     $clone;
966     }
967 wakaba 1.5
968 wakaba 1.14 my %_method_default_list = qw(new 1 parse 1 stringify 1 option 1 clone 1 method_available 1);
969     sub method_available ($$) {
970     my $self = shift;
971     my $name = shift;
972     return 1 if $_method_default_list{$name};
973     for (@{$self->{option}->{_METHODS}}) {
974     return 1 if $_ eq $name;
975     }
976     0;
977     }
978    
979 wakaba 1.30 sub import ($;%) {
980     my $self = shift;
981     my %option = @_;
982     for (keys %option) {
983     $DEFAULT{$_} = $option{$_};
984     }
985     if ($option{-body_default_charset} && !$option{-body_default_charset_input}) {
986     $DEFAULT{-body_default_charset_input} = $option{-body_default_charset};
987     }
988     if ($option{-header_default_charset} && !$option{-header_default_charset_input}) {
989     $DEFAULT{-header_default_charset_input} = $option{-header_default_charset};
990     }
991     }
992    
993 wakaba 1.9 =back
994    
995 wakaba 1.11 =head1 C<format>
996    
997     =over 2
998    
999     =item mail-rfc650
1000    
1001     Internet mail message, defined by IETF RFC 650
1002    
1003     =item mail-rfc724
1004    
1005     Internet mail message, defined by IETF RFC 724
1006    
1007     =item mail-rfc733
1008    
1009     Internet mail message, defined by IETF RFC 733
1010    
1011     =item mail-rfc822
1012    
1013     Internet mail message, defined by IETF RFC 822
1014    
1015 wakaba 1.35 =item mail-rfc822+rfc1123
1016    
1017     Internet mail message, defined by IETF RFC 822, ammended by RFC 1123
1018    
1019 wakaba 1.11 =item mail-rfc2822
1020    
1021     Internet mail message, defined by IETF RFC 2822
1022    
1023     =item mime-1.0
1024    
1025     MIME entity
1026    
1027     =item mime-1.0-rfc1341
1028    
1029     MIME entity, defined by RFC 1341 (and RFC 1342)
1030    
1031     =item mime-1.0-rfc1521
1032    
1033     MIME entity, defined by RFC 1521 and 1522
1034    
1035     =item mime-1.0-rfc2045
1036    
1037     MIME entity, defined by RFC 2045,..., 2049
1038    
1039     =item news-bnews
1040    
1041     Usenet Bnews format
1042    
1043     =item news-rfc850
1044    
1045     Usenet news format, defined by IETF RFC 850
1046    
1047     =item news-rfc1036
1048    
1049     Usenet news format, defined by IETF RFC 1036
1050    
1051     =item news-son-of-rfc1036
1052    
1053     Usenet news format, defined by son-of-RFC1036
1054    
1055     =item news-usefor
1056    
1057     Usenet news format, defined by usefor-article (IETF Internet Draft)
1058    
1059     =item http-1.0-rfc1945
1060    
1061     HTTP/1.0 message, defined by IETF RFC 1945
1062    
1063     =item http-1.0-rfc1945-request
1064    
1065     HTTP/1.0 request message, defined by IETF RFC 1945
1066    
1067     =item http-1.0-rfc1945-response
1068    
1069     HTTP/1.0 response message, defined by IETF RFC 1945
1070    
1071     =item http-1.1-rfc2068
1072    
1073     HTTP/1.1 message, defined by IETF RFC 2068
1074    
1075     =item http-1.1-rfc2068-request
1076    
1077     HTTP/1.1 request message, defined by IETF RFC 2068
1078    
1079     =item http-1.1-rfc2068-response
1080    
1081     HTTP/1.1 response message, defined by IETF RFC 2068
1082    
1083     =item http-1.1-rfc2616
1084    
1085     HTTP/1.1 message, defined by IETF RFC 2616
1086    
1087     =item http-1.1-rfc2616-request
1088    
1089     HTTP/1.1 request message, defined by IETF RFC 2616
1090    
1091     =item http-1.1-rfc2616-response
1092    
1093     HTTP/1.1 response message, defined by IETF RFC 2616
1094    
1095     =item http-cgi-1.1
1096    
1097     CGI/1.1 output (for HTTP), defined by coar-cgi-v11 (IETF Internet Draft)
1098    
1099     =item http-cgi-1.2
1100    
1101     CGI/1.2 output, defined by coar-cgi-v12 (to be IETF Internet Draft)
1102    
1103     =item http-sip-2.0
1104    
1105     SIP/2.0 message, defined by IETF RFC 2543
1106    
1107     =item http-sip-2.0-request
1108    
1109     SIP/2.0 request message, defined by IETF RFC 2543
1110    
1111     =item http-sip-2.0-response
1112    
1113     SIP/2.0 response message, defined by IETF RFC 2543
1114    
1115     =item http-sip-cgi
1116    
1117     SIP/2.0 CGI (IETF Internet Draft)
1118    
1119     =item cpim-1.0
1120    
1121     CPIM/1.0 (IETF Internet Draft)
1122    
1123 wakaba 1.35 =item uri-url-mailto
1124 wakaba 1.12
1125     mailto: URL scheme
1126    
1127     =item uri-url-mailto-rfc1738
1128    
1129     mailto: URL scheme (defined by RFC 1738)
1130    
1131 wakaba 1.35 =item uri-url-mailto-rfc2368
1132 wakaba 1.12
1133     mailto: URL scheme (defined by RFC 2368)
1134    
1135 wakaba 1.35 =item uri-url-mailto-to
1136 wakaba 1.12
1137     C<to> part of mailto: URL scheme (for internal use only)
1138    
1139 wakaba 1.11 =back
1140    
1141 wakaba 1.1 =head1 EXAMPLE
1142    
1143     use Message::Entity;
1144 wakaba 1.9 my $msg = new Message::Entity From => '[email protected]',
1145     Subject => 'Example message',
1146     To => '[email protected]',
1147     -format => 'mail-rfc2822',
1148     body => $body;
1149 wakaba 1.1 $msg->header ($header);
1150     $msg->body ($body);
1151     print $msg;
1152    
1153 wakaba 1.3 =head1 SEE ALSO
1154    
1155     Message::* Perl modules
1156     <http://suika.fam.cx/~wakaba/Message-pm/>
1157    
1158 wakaba 1.1 =head1 LICENSE
1159    
1160     Copyright 2002 wakaba E<lt>[email protected]<gt>.
1161    
1162     This program is free software; you can redistribute it and/or modify
1163     it under the terms of the GNU General Public License as published by
1164     the Free Software Foundation; either version 2 of the License, or
1165     (at your option) any later version.
1166    
1167     This program is distributed in the hope that it will be useful,
1168     but WITHOUT ANY WARRANTY; without even the implied warranty of
1169     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1170     GNU General Public License for more details.
1171    
1172     You should have received a copy of the GNU General Public License
1173     along with this program; see the file COPYING. If not, write to
1174     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1175     Boston, MA 02111-1307, USA.
1176    
1177     =head1 CHANGE
1178    
1179     See F<ChangeLog>.
1180 wakaba 1.37 $Date: 2002/08/01 09:20:34 $
1181 wakaba 1.1
1182     =cut
1183    
1184     1;

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24