/[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.36 - (hide annotations) (download)
Thu Aug 1 09:20:34 2002 UTC (24 years ago) by wakaba
Branch: MAIN
Changes since 1.35: +57 -4 lines
2002-08-01  Wakaba <w@suika.fam.cx>

	* Entity.pm (list_name, list_count): New methods.

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.24