Re: Email::Address::XS

2017-01-23 Thread pali
On Saturday 14 January 2017 21:32:57 p...@cpan.org wrote:
> On Sunday 04 September 2016 00:24:56 Ricardo Signes wrote:
> > If we never *store* objects, but only produce them as requested, then
> > I think the total needed changes are -- but I'm sure I'll miss
> > things -- as follows:
> > 
> > * allow header_str and header args to Email::MIME->create to include
> >   objects, which are immediately asked to encode themselves for
> >   storage
> > * add header_as_obj that takes a header name and, optionally, a class
> >   name and offset (an offset so you can ask for an object of the nth
> >   Received header)
> > * a registry used by header_as_obj to get a default class name from
> >   header name
> 
> So lets move. This is implemented in my pull request: 
> https://github.com/rjbs/Email-MIME/pull/35
> 
> Default class name for header name is retrieved from hash:
> Email::MIME::Header::header_to_class_map
> 
> Comments and review is welcome!

rjbs, can you review my pull request?


Re: Email::Address::XS

2016-11-12 Thread pali
On Sunday 04 September 2016 00:24:56 Ricardo Signes wrote:
> If we never *store* objects, but only produce them as requested, then
> I think the total needed changes are -- but I'm sure I'll miss
> things -- as follows:
> 
> * allow header_str and header args to Email::MIME->create to include
>   objects, which are immediately asked to encode themselves for
>   storage
> * add header_as_obj that takes a header name and, optionally, a class
>   name and offset (an offset so you can ask for an object of the nth
>   Received header)

As prerequisite for offset small change to Email::Simple is needed. 
Currently Email::Simple cannot returns just nth value for header with 
specified name. Support for this is in new pull request: 
https://github.com/rjbs/Email-Simple/pull/16

> * a registry used by header_as_obj to get a default class name from
>   header name


Re: Email::Address::XS

2016-11-12 Thread pali
On Monday 05 September 2016 10:25:11 p...@cpan.org wrote:
> On Saturday 03 September 2016 18:24:56 Ricardo Signes wrote:
> > The Email::MIME changes look like they could be broken up into
> > several PRs, some of which would be obviously good to apply
> > immediately, like removals of dead code and pointers to bad
> > modules.
> 
> If you think that some of those changes can be merged immediately,
> please specify commits and I create new pull request for them. Btw,
> I'm preparing another big patch series for Encode::MIME::Header
> module (call encode("MIEM-Header", ...)) which will fix remaining
> bugs. So if you know about some in that, let me know ASAP, so I can
> fix it in my patch series ;-)

New Encode was released with my fixes to MIME-Header...
https://metacpan.org/pod/Encode::MIME::Header

> ..Which means that removing pointer to that module will not be
> needed..

Now I created pull request for Email::MIME:
https://github.com/rjbs/Email-MIME/pull/32

It should contains only code cleanup and fixes, no Email::Address::XS... 
Look at it and if there are some problems, let me know!


Re: Email::Address::XS

2016-09-28 Thread Ricardo Signes
* p...@cpan.org [2016-09-18T11:40:53]
> Currently passing string values of From/To/Cc/Bcc/... headers into 
> header_str() method is broken in Email::MIME. That is because 
> Email::MIME currently uses Email::Address for generating those header 
> values (which is broken) and then MIME encode those broken outputs.
> 
> Email::Address::XS has (looks like) correctly implemented formatter and 
> so it is needed to correctly MIME encode From/To/Cc/Bcc headers.

I suggest making Email::MIME use Email::Address::XS if it is available, and
adding Email::Address::XS to the recommended prereqs of Email::MIME.
The right behavior will be easy to get, and usually be installed, but it will
be possible to proceed with less correct behavior if you haven't got a compiler
(for some sad reason).

Part of the question is: how wrong do things go, in what circumstances, if
Email::Address is substituted for Email::Address::XS.

> As compromise could be: Whole Email::MIME will not depends on module 
> Email::Address::XS. But if somebody want to pass Unicode string (via 
> header_str) to Email::MIME then MIME encoding will be done via 
> Email::MIME::Header::AddressList (which will use Email::Address::XS). So 
> if caller encodes manually From/To/Cc/... headers and pass them via 
> header_raw() then Email::Address::XS will not be needed.

Specifically, I think, a non-ASCII string.  I'm guessing that most/many users
are really just passing in fixed ASCII strings, so this rule wouldn't affect
them at all.  Users passing in non-ASCII would start getting a "automatic
encoding of non-ASCII $field header requires " error.  Seems okay.

> And can be Email::MIME::Header::AddressList part of Email-MIME 
> distribution (even if only this module will depends on XS)?

I guess so.  We need to mark this stuff experimental for a while, I think, too.

-- 
rjbs


signature.asc
Description: Digital signature


Re: Email::Address::XS

2016-09-18 Thread pali
On Sunday 18 September 2016 17:26:11 Ricardo Signes wrote:
> * p...@cpan.org [2016-09-17T19:05:51]
> 
> > $class->from_mime_string() will take raw MIME encoded string and
> > returns new object of $class (which will have decoded string
> > parts) $object->as_mime_string() will convert (Unicode) $object
> > into raw MIME encoded string
> > 
> > It is OK for you?
> 
> That all sounded fine.  I think the paragraph I left quoted
> overspecifies a bit.  Whether the object is storing things decoded
> or not isn't any of our concern as long as it has those two methods.
>  But I think we're on the same page.

OK!

> The Email::Address::XS use should be optional, as right now people
> can install Email::MIME in an compiler-free environment.  We can add
> it as a recommended prereq.

Currently passing string values of From/To/Cc/Bcc/... headers into 
header_str() method is broken in Email::MIME. That is because 
Email::MIME currently uses Email::Address for generating those header 
values (which is broken) and then MIME encode those broken outputs.

Email::Address::XS has (looks like) correctly implemented formatter and 
so it is needed to correctly MIME encode From/To/Cc/Bcc headers.

I started working on Email::MIME::Header::AddressList module (which will 
have from_mime_string() and as_mime_string() methods for From/To/Cc/Bcc 
headers) and this module cannot work without Email::Address::XS.

So what to do with currently broken From/To/Cc/Bcc/... headers 
(incorrectly MIME encoded) which Email::MIME generate? I do not see 
other option as dependency on Email::Address::XS.

As compromise could be: Whole Email::MIME will not depends on module 
Email::Address::XS. But if somebody want to pass Unicode string (via 
header_str) to Email::MIME then MIME encoding will be done via 
Email::MIME::Header::AddressList (which will use Email::Address::XS). So 
if caller encodes manually From/To/Cc/... headers and pass them via 
header_raw() then Email::Address::XS will not be needed.

But when it pass Unicode string for From/To/Cc/.. headers via header_str 
then it Email::MIME will loads Email::MIME::Header::AddressList which 
depends on Email::Address::XS...

It is acceptable?

And can be Email::MIME::Header::AddressList part of Email-MIME 
distribution (even if only this module will depends on XS)?


Re: Email::Address::XS

2016-09-17 Thread pali
On Saturday 17 September 2016 00:37:40 Ricardo Signes wrote:
> * p...@cpan.org [2016-09-12T03:26:52]
> 
> > And as I wrote if Email::MIME is not good place, then what about
> > other modules like Email::MIME::Header::Address (or invent other
> > name) which will use Address parse/format functions and will also
> > do that MIME encode/decode procedure? We can maybe add classes
> > also for other headers (like you suggested for DKIM signatures,
> > etc...).
> 
> I had started to write a lot of reply on the previous parts of your
> email, but I think that this is the only part that really matters in
> the end.  Yes, I think some thing like that is sufficient.  In the
> end, I think what's best is:
> 
> * a thing that can take a raw (encoded) header string and give you an
> object * ...which is an object with access to the header's
> structured data * ...which you can turn back into a raw header to
> store as needed
> 
> With that facility, people can plug in (header => class)
> configuration and things just go.  We can start off suggesting, for
> example, an address one.

Ok, so first step can be support passing blessed objects with 
as_mime_string() method into $email->header_str_set(). Object's 
as_mime_string() will be responsible for producing correct MIME-encoded 
header value

Next, I believe we agreed on $email->header_as_obj($name, $class) method 
which will return object for header name of class. It can use e.g. 
$class->from_mime_string() method for creating object. (Plus there will 
be some registration mechanism to predefine $name => $class mapping, so 
$class argument does not needs to be mandatory).

I think these two parts should be enough for Email::MIME API from user 
of Email::MIME perspective.

And I would propose new module (e.g. Email::MIME::Header::AddressList) 
which will be in Email::MIME distribution and will represent list of 
Email::Address::XS objects with own implementation of ->as_mime_string() 
and ->from_mime_string() methods. That could be used for passing 
list/groups of Email::Address::XS objects into Email::MIME and also get 
them via header_as_obj() API.

$class->from_mime_string() will take raw MIME encoded string and returns 
new object of $class (which will have decoded string parts)
$object->as_mime_string() will convert (Unicode) $object into raw MIME 
encoded string

It is OK for you?


Re: Email::Address::XS

2016-08-23 Thread pali
On Monday 22 August 2016 22:26:09 Ricardo Signes wrote:
> Here's a verbose form:
> 
>   # Get an email.
>   my $email   = get_some_email_mime();
> 
>   # Get the header -- the (unfolded) raw bytes.
>   my $cc_hdr  = $email->header_raw('Original-CC');
> 
>   # parse it into an object
>   my $cc_obj  = parse_mailboxes( $cc_obj );
> 
>   # put that object into the header:
>   $email->header_set('Original-CC', $cc_obj);
> 
>   # get the raw mime-encoded bytes again:
>   my $cc_hdr2 = $email->header_raw('Original-CC');
> 
>   # get a list of sub-object from the object's imaginary interface:
>   my @boxes   = $email->header_obj('Original-CC')->boxes;

That is really bad API :-( User of Email::MIME is really not interested
in getting RAW header and then manually converting it to some object
(provided by parse_mailboxes), then putting it back to Email::MIME
object... Email::MIME is there for doing whole MIME encoding/decoding
and basically user should not need to call any RAW method (only in case
when he needs to manually encode/decode MIME parts).

And I would expect from Email::MIME to do that encoding/decoding also
for From, To, CC... headers...


Re: Email::Address::XS

2016-08-22 Thread Ricardo Signes
* p...@cpan.org [2016-08-20T06:01:16]
> Email::MIME is module which automatically do any MIME encoding/decoding 
> without user interaction, so that decoding must be done automatically 
> and without such "upgrade" function.

So do you mean that whenever someone reads the header with a specific method,
the header is parsed just-in-time?

If so, this seems like something very easy to add in an Email::MIME subclass to
show it off.

Of course, it's also easy to take the hypothetical code behind
"upgrade_headers($email)" to do something just like this, on a per-known-header
basis.

> I do not want to do that decode manually or call some "upgrade" function 
> which you propose... Reading one email header should not change internal 
> email structure.

I never suggested that anything was changed by virtue of being read, but rather
that one could explictly upgrade structures if desired.

> Also it must be possible to get either named groups from Original-Cc 
> header or only list of addresses. And I think with your proposal API it 
> is not possible. You would need to call some "downgrade" function and 
> then "upgrade" it to another object or so...

Why would this not be possible?  There is some object storing the mailboxes
structure, and it provides methods that answer the questions one needs to ask.

-- 
rjbs


signature.asc
Description: Digital signature


Email::Simple & Email::MIME with Email::Address::XS

2016-08-21 Thread pali
Hi!

Now after long discussion which started 3 months ago and not finished 
yet about Email::Address::XS support in Email::MIME I started to writing 
code... I want to have something working, usable and not never-ending 
discussion.

I implemented new module Email::Address::List::XS which provides object 
representation of list of Email::Address::XS objects with parse() and 
format() methods.

Next I added support for Email::Address::List::XS objects into 
Email::Simple and Email::MIME modules.

All source code is available at:
https://github.com/pali/Email-Address-XS/tree/list
https://github.com/rjbs/Email-Simple/compare/master...pali:master
https://github.com/rjbs/Email-MIME/compare/master...pali:master

Example of usage:

my $email = Email::Simple->create(
header => [
From => Email::Address::XS->new('Name' => 'user@host'),
To => '"My Name" <us...@example.com>',
    ],
);
my $addr1 = Email::Address::XS->new(undef, 'addre...@example.com');
my $addr2 = Email::Address::XS->new(undef, 'addre...@example.com');
my $addrlist = Email::Address::List::XS->new($addr1, $addr2);
$email->header_raw_set(Cc => $addrlist);

Email::Simple can accept any object which has format() method. Both 
modules Email::Address::List::XS and Email::Address::XS provides them.

Email::Simple contains new method header_addrlist_raw() which returns 
Email::Address::List::XS object for specified header (it does not matter 
if header value was passed as object or as string).

my $addrlist_to = $email->header_addrlist_raw('To');
my $phrase = $addrlist_to->first_address()->phrase();

(Now $phrase contains string 'My Name').

Next situation with Email::MIME is a bit complicated as module 
Email::MIME is responsible for doing MIME encoding/decoding. And because 
$address needs to be specially MIME encoded and decoded it is not 
possible to accept arbitrary object with format() method as in 
Email::Simple module. Email::MIME needs to know how to each object 
correctly encode and decode...

So for Email::MIME I added object support only for Email::Address::XS 
and Email::Address::List::XS modules. I do not expect that there will be 
needed support for anything else...

Usage is same as for Email::Simple, just in create() method is used 
"header_str" argument and for retrieving Email::Address::List::XS object 
is used header_addrlist() method. Basically same as work with strings 
(raw methods have _raw suffix). Passing objects to _raw methods just 
cause that objects will not be MIME encoded.

Look at code and tell me if this Email::Address::List::XS module is 
usable and if patches for Email::Simple and Email::MIME are acceptable. 
If yes, I can clean up it, write some tests and release whole 
Email::Address::XS module to CPAN...


Re: Email::Address::XS

2016-08-01 Thread Ricardo Signes
* p...@cpan.org [2016-07-12T11:43:02]
> On Monday 04 July 2016 01:52:41 Ricardo Signes wrote:
> > 
> > I'd stick to header_str, I think, but I'm not sure.  At any rate:
> > yes.
> 
> And this is what I do not like... to pass objects to function with name 
> header_str. That name sounds like it takes string, not object (or more 
> objects)...

Either we can add a new name, so people end up having to give "header_str" and
"header_obj" or we can say "in general everything uses header_str, which
follows these simple rules."  I would rather do that.

> > > Still do not know how to handle non-MIME headers correctly in
> > > Email::MIME module. We can either create blacklist of non-MIME
> > > headers and extend it every time when somebody report problem or
> > > create whitelist of MIME headers... Or let caller to decide if his
> > > header must be MIME-encoded or not.
> > 
> > I'm sorry, I don't understand.  Could you elaborate?
> 
> If passed pair (header-name, header-value) needs to be MIME encoded or 
> not. Currently there is blacklist in Email::MIME for header names which 
> are never MIME encoded (like Message-Id, Date, ...) when passing as 
> header_str.

So, I'd assume we'd go forward with:

* if you know exactly octets you, the user, want in the header field, use
  "header", but this is likely rare
* if you want to provide a string for a field that's pretty much just a string,
  use header_str and if it requires special handling, we do our best, which
  should get better over time
* but if things are complicated, use an object that represents the structured
  data

I don't like the idea that this will be broken further by adding the object
behavior, though.

  $email->header_str_set($field => $email->header($field));

...should not break things.

> > "header_str" is "text string" which means it will get encoded.
> 
> Not exactly, there are exceptions (Message-Id, Date, ...) plus special 
> behaviour for addresses headers.

Those /mostly/ still get encoded, but we know that the strings are meant to be
structured, so we try to deconstruct them and encode them correctly.
I think those fields that get passed through unchanged are probably in error at
least insofar as they let you put non-7-bit-clean data in your headers.  This
should probably be fatal:

  header_str => [ Date => "\N{SMILING FACE WITH HORNS}" ]

> Addresses and groups are really something different as previous types 
> (strings). And if we threat them as objects, I would rather see e.g. 
> header_obj (or other different name) instead mixing it again with 
> header_str (which already have exceptions :-(). This is my initial 
> reason for header_addr/grps to distinguish it.

My feeling is that Perl programmers are used to polymorphic interfaces, and
that multiplying the number of ways to specify headers is a needless confusion.
What is the benefit to the end user of splitting things up?

-- 
rjbs


signature.asc
Description: Digital signature


Re: Email::Address::XS

2016-07-12 Thread pali
On Monday 04 July 2016 01:52:41 Ricardo Signes wrote:
> * p...@cpan.org [2016-07-03T08:39:22]
> 
> > On Friday 01 July 2016 02:51:31 Ricardo Signes wrote:
> > > What if we defined a role (here, just a well-known name) called
> > > Email::MIME::Header::Value, which is used to signal that a
> > > particular method, say "as_mime_header", should be used to
> > > stringify?
> > 
> > In this case, do we need role at all? Is not existence of method
> > "as_mime_header" enough?
> 
> That method alone is fine with me.
> 
> > And all this would be passed via header or header_str?
> 
> I'd stick to header_str, I think, but I'm not sure.  At any rate:
> yes.

And this is what I do not like... to pass objects to function with name 
header_str. That name sounds like it takes string, not object (or more 
objects)...

> > If address(), addrlist() and addrgroup() returns those objects
> > (with as_mime_header() method) it could be usable...
> > 
> > But I was thinking about using same syntax in Email::MIME for
> > passing addrlist/addrgroup as is in Email::Address::XS
> > format_email_addresses and format_email_groups functions.
> 
> I'm afraid I don't understand what you mean.

Syntax/API of passing email groups to function format_email_groups from 
Email::Address::XS module. E.g. to call format_email_groups and 
Email::MIME functions with same syntax of objects/structures/arguments..

> > In my opinion folding and unfolding should be done in
> > Email::Simple. I'm not huge fan of adding folding and CRLF code
> > into Email::Address::XS as it has nothing to do with it. That
> > module parse and format one line of list of addresses.
> 
> I agree.  I think if we start with the API described above, and leave
> the folding for the message to perform, we'll be okay.  We can
> certainly find out by writing the code!
> 
> > > What do you think of this all?
> > 
> > Still do not know how to handle non-MIME headers correctly in
> > Email::MIME module. We can either create blacklist of non-MIME
> > headers and extend it every time when somebody report problem or
> > create whitelist of MIME headers... Or let caller to decide if his
> > header must be MIME-encoded or not.
> 
> I'm sorry, I don't understand.  Could you elaborate?

If passed pair (header-name, header-value) needs to be MIME encoded or 
not. Currently there is blacklist in Email::MIME for header names which 
are never MIME encoded (like Message-Id, Date, ...) when passing as 
header_str.

> > Basically we need unambiguous way to specify:
> > 
> > * ascii string which will never be MIME-encoded (error for unicode
> > char)
> > * unicode string which will be MIME-encoded if contains
> > unicode char
> > * addresses/groups - but again with ability to
> > specify if do MIME-encode
> 
> We have that, right?
> 
> "header" is "already encoded", which is another way of saying "do not
> encode this."

Yes.

> "header_str" is "text string" which means it will get encoded.

Not exactly, there are exceptions (Message-Id, Date, ...) plus special 
behaviour for addresses headers.

> The address or groups thing falls under "object."  I had assumed it
> would, itself, know how to become MIME encoded.  This is important,
> because the semantics of what gets encoded differ per field type. 
> So, as_mime_header is the encoded form.  If you want to offer an
> unencoded form, as_string seems like the obvious method.

Addresses and groups are really something different as previous types 
(strings). And if we threat them as objects, I would rather see e.g. 
header_obj (or other different name) instead mixing it again with 
header_str (which already have exceptions :-(). This is my initial 
reason for header_addr/grps to distinguish it.


Re: Email::Address::XS

2016-07-03 Thread Ricardo Signes
* p...@cpan.org [2016-07-03T08:39:22]
> On Friday 01 July 2016 02:51:31 Ricardo Signes wrote:
> 
> > What if we defined a role (here, just a well-known name) called
> > Email::MIME::Header::Value, which is used to signal that a particular
> > method, say "as_mime_header", should be used to stringify?
> 
> In this case, do we need role at all? Is not existence of method 
> "as_mime_header" enough?

That method alone is fine with me.

> And all this would be passed via header or header_str?

I'd stick to header_str, I think, but I'm not sure.  At any rate: yes.

> If address(), addrlist() and addrgroup() returns those objects (with 
> as_mime_header() method) it could be usable...
> 
> But I was thinking about using same syntax in Email::MIME for passing 
> addrlist/addrgroup as is in Email::Address::XS format_email_addresses 
> and format_email_groups functions.

I'm afraid I don't understand what you mean.

> In my opinion folding and unfolding should be done in Email::Simple. I'm 
> not huge fan of adding folding and CRLF code into Email::Address::XS as 
> it has nothing to do with it. That module parse and format one line of 
> list of addresses.

I agree.  I think if we start with the API described above, and leave the
folding for the message to perform, we'll be okay.  We can certainly find out
by writing the code!

> > What do you think of this all?
> 
> Still do not know how to handle non-MIME headers correctly in 
> Email::MIME module. We can either create blacklist of non-MIME headers 
> and extend it every time when somebody report problem or create 
> whitelist of MIME headers... Or let caller to decide if his header must 
> be MIME-encoded or not.

I'm sorry, I don't understand.  Could you elaborate?

> Basically we need unambiguous way to specify:
> 
> * ascii string which will never be MIME-encoded (error for unicode char)
> * unicode string which will be MIME-encoded if contains unicode char
> * addresses/groups - but again with ability to specify if do MIME-encode

We have that, right?

"header" is "already encoded", which is another way of saying "do not encode
this."

"header_str" is "text string" which means it will get encoded.

The address or groups thing falls under "object."  I had assumed it would,
itself, know how to become MIME encoded.  This is important, because the
semantics of what gets encoded differ per field type.  So, as_mime_header is
the encoded form.  If you want to offer an unencoded form, as_string seems like
the obvious method.

-- 
rjbs


signature.asc
Description: Digital signature


Re: Email::Address::XS

2016-07-03 Thread pali
On Friday 01 July 2016 02:51:31 Ricardo Signes wrote:
> My coworkers have returned to the other side of the world!  I
> attended YAPC!  i had a vacation!  I am back.
> 
> * p...@cpan.org [2016-06-01T12:44:01]
> 
> > On Tuesday 31 May 2016 02:42:48 Ricardo Signes wrote:
> > > * p...@cpan.org [2016-05-28T16:48:40]
> > > 
> > > > Basically yes. From caller perspective I want to pass email
> > > > address object and let Email::MIME to do MIME encoding
> > > > correctly. Something like this:
> > > > 
> > > > my $email = Email::MIME->create(
> > > > 
> > > > header_addr => [ ... ],
> > > > 
> > > > );
> > > 
> > > I think that requiring people to break headers up even further
> > > into to add a "header_addr" argument is a bit much.  And why
> > > header_grps?
> 
> So, you had some responses to this which were quite helpful.
> 
> My suggestion was meant to be something like "why not make
> Email::MIME understand some kind of object as the value in a
> header?"  I think this is still right.
> 
> Your main responses were (please correct me if I am misunderstanding
> them):
> 
> 1.  it should be possible and easy to supply a list of address
> objects
> 2.  it should be possible to have a named group, but not
> required

Both 1. and 2. are required and 1. should be easy to use by caller. 2. 
is not so common, but still email module should be able to support such 
thing.

> 3.  we don't want ambiguity in how objects passed to
> (header_str => [...]) are interpreted

Yes!

> What if we defined a role (here, just a well-known name) called
> Email::MIME::Header::Value, which is used to signal that a particular
> method, say "as_mime_header", should be used to stringify?

In this case, do we need role at all? Is not existence of method 
"as_mime_header" enough?

> When building the header, the code will do something like:
> 
>   $string = $name . ": "
>   . ($value->DOES('Email::MIME::Header::Value')
>           ? $value->as_mime_header
> 
>   : "$value");
> 
> No existing object will become confused by this change, only objects
> which do the new role.
> 
> Then Email::Address::XS could provide some helper routines, so you
> could write and of:
> 
> From => 'r...@cpan.org'
> 
> From => Email::Address::XS->new(...)
> 
> From => address('r...@cpan.org', 'Ricardo SIGNES')
> 
> From => addrlist( address('r...@cpan.org', 'Ricardo SIGNES'), ...
> )
> 
> From => addrgroup( Humans => address('r...@cpan.org', 'Rik'), ...
> )

And all this would be passed via header or header_str?

If address(), addrlist() and addrgroup() returns those objects (with 
as_mime_header() method) it could be usable...

But I was thinking about using same syntax in Email::MIME for passing 
addrlist/addrgroup as is in Email::Address::XS format_email_addresses 
and format_email_groups functions.

> It might be best to make the first code sample actually do:
> 
>   $string = $name . ": "
>   . ($value->DOES('Email::MIME::Header::Value')
>       ? $value->as_mime_header($name, $mycrlf)  # <-- changed
> 
>   : "$value");
> 
> ...to let the object do folding.  I'm not sure about that one.  I'd
> want to double-check whether there's a reason to not always do the
> folding of the post-stringified form in Email::MIME.

In my opinion folding and unfolding should be done in Email::Simple. I'm 
not huge fan of adding folding and CRLF code into Email::Address::XS as 
it has nothing to do with it. That module parse and format one line of 
list of addresses.

I think that automatically adding CRLF into output string is not good 
idea. But maybe it could make sense to tell Email::Address::XS module to 
"prepare" output string in format that it can be split by greedy 
algorithm for lines which are XX chars long (maybe 72 by default?).

But now I'm not sure if it is possible... Email::Address::XS know 
nothing about MIME or encodings. It just format what caller pass it...

> Anyway, this avoids adding multiple more places to set headers and
> makes the API extensible for other header types like Message-ID,
> etc, in the future.
> 
> What do you think of this all?

Still do not know how to handle non-MIME headers correctly in 
Email::MIME module. We can either create blacklist of non-MIME headers 
and extend it every time when somebody report problem or create 
whitelist of MIME headers... Or let caller to decide if his header must 
be MIME-encoded or not.

And I think that it is better to let caller de

Re: Email::Address::XS

2016-06-30 Thread Ricardo Signes

My coworkers have returned to the other side of the world!  I attended YAPC!  i
had a vacation!  I am back.

* p...@cpan.org [2016-06-01T12:44:01]
> On Tuesday 31 May 2016 02:42:48 Ricardo Signes wrote:
> > * p...@cpan.org [2016-05-28T16:48:40]
> > 
> > > Basically yes. From caller perspective I want to pass email address
> > > object and let Email::MIME to do MIME encoding correctly. Something
> > > like this:
> > > 
> > > my $email = Email::MIME->create(
> > > 
> > >   header_addr => [ ... ],
> > > 
> > > );
> > 
> > I think that requiring people to break headers up even further into
> > to add a "header_addr" argument is a bit much.  And why header_grps?

So, you had some responses to this which were quite helpful.

My suggestion was meant to be something like "why not make Email::MIME
understand some kind of object as the value in a header?"  I think this is
still right.

Your main responses were (please correct me if I am misunderstanding them):

1.  it should be possible and easy to supply a list of address objects
2.  it should be possible to have a named group, but not required
3.  we don't want ambiguity in how objects passed to (header_str => [...])
are interpreted

What if we defined a role (here, just a well-known name) called
Email::MIME::Header::Value, which is used to signal that a particular method,
say "as_mime_header", should be used to stringify?

When building the header, the code will do something like:

  $string = $name . ": "
  . ($value->DOES('Email::MIME::Header::Value')
      ? $value->as_mime_header
  : "$value");

No existing object will become confused by this change, only objects which do
the new role.

Then Email::Address::XS could provide some helper routines, so you could write
and of:

From => 'r...@cpan.org'

From => Email::Address::XS->new(...)

From => address('r...@cpan.org', 'Ricardo SIGNES')

From => addrlist( address('r...@cpan.org', 'Ricardo SIGNES'), ... )

From => addrgroup( Humans => address('r...@cpan.org', 'Rik'), ... )

It might be best to make the first code sample actually do:

  $string = $name . ": "
  . ($value->DOES('Email::MIME::Header::Value')
  ? $value->as_mime_header($name, $mycrlf)  # <-- changed
  : "$value");

...to let the object do folding.  I'm not sure about that one.  I'd want to
double-check whether there's a reason to not always do the folding of the
post-stringified form in Email::MIME.

Anyway, this avoids adding multiple more places to set headers and makes the
API extensible for other header types like Message-ID, etc, in the future.

What do you think of this all?

-- 
rjbs


signature.asc
Description: Digital signature


Re: Email::Address::XS

2016-05-30 Thread Ricardo Signes
* p...@cpan.org [2016-05-28T16:48:40]
> Basically yes. From caller perspective I want to pass email address 
> object and let Email::MIME to do MIME encoding correctly. Something like 
> this:
> 
> my $email = Email::MIME->create(
>   header_addr => [ ... ],
> );

I think that requiring people to break headers up even further into to add
a "header_addr" argument is a bit much.  And why header_grps?  How about object
that represents the group?  Then the existing header and header_str arguments
can start silently accepting these objects and doing the right thing.

-- 
rjbs


signature.asc
Description: Digital signature


Re: Email::Address::XS

2016-05-28 Thread pali
On Saturday 28 May 2016 22:33:02 Ricardo Signes wrote:
> > Thanks to named group support I would like to extend Email::MIME
> > module to allow passing directly Email::Address::XS objects, not
> > only string headers to make MIME encoding and decoding from
> > applications easier.
> > 
> > What do you think about it?
> 
> I'm not sure what you're suggesting.  Do you mean:
> 
>   Email::MIME->create(..., header => [ To => $addr_xs, ...  ]);
> 
> ...as opposed to:
> 
>   Email::MIME->create(..., header => [ To => $addr_xs->as_string, ...
>  ]);
> 
> ?  Could you elaborate?

Basically yes. From caller perspective I want to pass email address 
object and let Email::MIME to do MIME encoding correctly. Something like 
this:

my $email = Email::MIME->create(
header_addr => [
From => Email::Address::XS->new(Name => 'user@host'),
    To => [
        Email::Address::XS->new(Name2 => 'user2@host'),
Email::Address::XS->new(Name3 => 'user3@host'),
],
],
);

Currently Email::MIME module takes UTF-8 formatted To (or Cc) header, 
construct from it Email::Address object, then MIME encode phrase part 
and after that format header back to string line.

If I pass Email::Address::XS object directly to Email::MIME, then one 
step of decomposition (from ->as_string back to Email::Address object) 
will not be needed.

Also in same way I would to pass named group of email addresses, e.g:

my $email = Email::MIME->create(
header_grps => [
To => [
$group_name => [ $address1_obj, $address2_obj ],
    ],
    ],
);

Currently Email::MIME from all named groups, because it uses 
Email::Address parser and it does not support it.

My Email::Address::XS supports also named groups of addresses, so above 
syntax can be implemented via Email::Address::XS module.


Re: Email::Address::XS

2016-05-28 Thread Ricardo Signes
* p...@cpan.org [2016-05-23T13:05:39]
> I created new perl module Email::Address::XS for parsing and formatting
> email groups or addresses. Parser is borrowed from dovecot and that part
> implemented in C/XS.

Cool!

> Thanks to named group support I would like to extend Email::MIME module
> to allow passing directly Email::Address::XS objects, not only string
> headers to make MIME encoding and decoding from applications easier.
> 
> What do you think about it?

I'm not sure what you're suggesting.  Do you mean:

  Email::MIME->create(..., header => [ To => $addr_xs, ...  ]);

...as opposed to:

  Email::MIME->create(..., header => [ To => $addr_xs->as_string, ...  ]);

?  Could you elaborate?

-- 
rjbs


signature.asc
Description: Digital signature


Email::Address::XS

2016-05-23 Thread pali
Hello!

I created new perl module Email::Address::XS for parsing and formatting
email groups or addresses. Parser is borrowed from dovecot and that part
implemented in C/XS.

Source code is currently at:
https://github.com/pali/Email-Address-XS

Email::Address::XS has backward compatible API with old Email::Address
module (which has security problem CVE-2015-7686) and my new module is
intended to replace old Email::Address.

This module supports not only single list of addresses, but also named
groups of addresses (according to RFC 2822).

I tried to make source code readable, documented and also fast (thanks
to dovecot parser written in C; not in perl regex).

It contains also lot of examples and test cases to check that parser and
formatter is correct.

See pod documentation and unit tests:
https://github.com/pali/Email-Address-XS/blob/master/lib/Email/Address/XS.pm
https://github.com/pali/Email-Address-XS/blob/master/t/Email-Address-XS.t

Thanks to named group support I would like to extend Email::MIME module
to allow passing directly Email::Address::XS objects, not only string
headers to make MIME encoding and decoding from applications easier.

What do you think about it?