File Coverage

lib/Mail/Make/Headers/MessageID.pm
Criterion Covered Total %
statement 30 60 50.0
branch 0 10 0.0
condition 0 5 0.0
subroutine 10 19 52.6
pod 5 7 71.4
total 45 101 44.5


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## MIME Email Builder - ~/lib/Mail/Make/Headers/MessageID.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2026 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2026/03/02
7             ## Modified 2026/03/03
8             ## All rights reserved.
9             ##
10             ## This program is free software; you can redistribute it and/or modify it
11             ## under the same terms as Perl itself.
12             ##----------------------------------------------------------------------------
13             package Mail::Make::Headers::MessageID;
14             BEGIN
15             {
16 9     9   52 use strict;
  9         19  
  9         320  
17 9     9   37 use warnings;
  9         14  
  9         676  
18 9     9   1062 warnings::register_categories( 'Mail::Make' );
19 9     9   51 use parent qw( Module::Generic );
  9         26  
  9         56  
20 9     9   682 use vars qw( $VERSION $EXCEPTION_CLASS );
  9         22  
  9         450  
21 9     9   953 use Data::UUID;
  9         1423  
  9         707  
22 9     9   80 use Mail::Make::Exception;
  9         52  
  9         100  
23             use overload
24             (
25             '""' => 'as_string',
26 0     0   0 bool => sub { 1 },
27 9     9   2889 );
  9         28  
  9         77  
28 9         15 our $EXCEPTION_CLASS = 'Mail::Make::Exception';
29 9         213 our $VERSION = 'v0.2.0';
30             };
31              
32 9     9   93 use strict;
  9         22  
  9         254  
33 9     9   38 use warnings;
  9         13  
  9         4770  
34              
35             sub init
36             {
37 0     0 1   my $self = shift( @_ );
38 0           $self->{_id} = undef;
39 0           $self->{_exception_class} = $EXCEPTION_CLASS;
40 0           my $id = shift( @_ );
41 0 0         $self->SUPER::init( @_ ) || return( $self->pass_error );
42 0 0 0       if( defined( $id ) && length( $id ) )
43             {
44 0 0         $self->id( $id ) || return( $self->pass_error );
45             }
46             else
47             {
48 0           $self->{_id} = $self->_generate;
49             }
50 0           return( $self );
51             }
52              
53             sub as_string
54             {
55 0     0 1   my $self = shift( @_ );
56 0   0       return( $self->{_id} // '' );
57             }
58              
59             # generate()
60             # Generates a new unique Message-ID string and sets it.
61             sub generate
62             {
63 0     0 1   my $self = shift( @_ );
64 0           $self->{_id} = $self->_generate;
65 0           return( $self );
66             }
67              
68             # id( [$value] )
69             # Gets or sets the Message-ID string. Must be in angle-bracket format
70             # <local-part@domain> per RFC 2822.
71             sub id
72             {
73 0     0 1   my $self = shift( @_ );
74 0 0         if( @_ )
75             {
76 0           my $val = shift( @_ );
77 0 0         unless( $val =~ /\A<[^>]+\@[^>]+>\z/ )
78             {
79 0           return( $self->error( "Message-ID must be in <local\@domain> format, got: '$val'" ) );
80             }
81 0           $self->{_id} = $val;
82 0           return( $self );
83             }
84 0           return( $self->{_id} );
85             }
86              
87             # value() - alias for as_string
88 0     0 1   sub value { return( shift->as_string ); }
89              
90             # _generate()
91             # Produces a unique <uuid@generated> string.
92             sub _generate
93             {
94 0     0     my $self = shift( @_ );
95 0           my $uuid = lc( Data::UUID->new->create_str );
96 0           $uuid =~ tr/-//d;
97 0           return( "<${uuid}\@mail.make.generated>" );
98             }
99              
100             # NOTE: STORABLE support
101 0     0 0   sub STORABLE_freeze { CORE::return( CORE::shift->FREEZE( @_ ) ); }
102              
103 0     0 0   sub STORABLE_thaw { CORE::return( CORE::shift->THAW( @_ ) ); }
104              
105             1;
106             # NOTE: POD
107             __END__
108              
109             =encoding utf-8
110              
111             =head1 NAME
112              
113             Mail::Make::Headers::MessageID - Typed Message-ID Header for Mail::Make
114              
115             =head1 SYNOPSIS
116              
117             use Mail::Make::Headers::MessageID;
118              
119             # Auto-generated ID
120             my $mid = Mail::Make::Headers::MessageID->new;
121             print $mid->as_string;
122             # <3f2504e04f8911d39a0c030648acfd0c@mail.make.generated>
123              
124             # Supplied ID
125             my $mid2 = Mail::Make::Headers::MessageID->new( '<abc@example.com>' );
126              
127             =head1 VERSION
128              
129             v0.2.0
130              
131             =head1 DESCRIPTION
132              
133             A typed object for the C<Message-ID> header field. Validates that any supplied value is in angle-bracket format, and auto-generates a UUID-based ID when none is supplied.
134              
135             =head1 CONSTRUCTOR
136              
137             =head2 new( [$id_string] )
138              
139             If C<$id_string> is omitted, a unique ID is auto-generated. If supplied, it must be in C<< <local-part@domain> >> format.
140              
141             =head1 METHODS
142              
143             =head2 as_string
144              
145             Returns the Message-ID string.
146              
147             =head2 generate
148              
149             Generates a fresh unique ID and replaces the current one.
150              
151             =head2 id( [$value] )
152              
153             Gets or sets the ID. Validates the angle-bracket format.
154              
155             =head2 value
156              
157             Alias for C<as_string>.
158              
159             =head1 AUTHOR
160              
161             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
162              
163             =head1 SEE ALSO
164              
165             RFC 2822 section 3.6.4
166              
167             L<Mail::Make::Headers>, L<Mail::Make>
168              
169             =head1 COPYRIGHT & LICENSE
170              
171             Copyright(c) 2026 DEGUEST Pte. Ltd.
172              
173             All rights reserved.
174              
175             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
176              
177             =cut