Re: Email::Address::XS

[email protected] (Ricardo Signes) Sat, 3 Sep 2016 18:24:56 -0400
Newsgroups perl.pep
Message-ID <20160903222456.GA22183@debian>
--0F1p//8PRICkK4MW
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

I know I'm taking a long time between replies.  Thanks for being patient.  =
I've
been rotating through "out of town" and "catching up with work backlog from
being out of town," basically, and in the leftover time, I don't have any b=
rain
left for anything much at all.  This week is another "all work all week" we=
ek,
but maybe the week after things will even out for a while.

* [email protected] [2016-08-25T03:40:20]
> On Wednesday 24 August 2016 22:55:05 Ricardo Signes wrote:
> >=20
> > I don't understand "you have no idea about arbitrary object."  Obviousl=
y you
> > would get a type of object based on the header in question.
>=20
> Then you need to create mapping from header name to object name. Plus
> this does not solve problems for extended/application specific header
> (X-Something) which can be used for type which application wants.

Yes, you need that mapping, and you extend it on an application-specific ba=
sis.

> > This reads like, "Look, just use the API that you don't like because I
> > already
>=20
> It is not like it...

I apologize, this was an impolite response.

> I would rather know what is wrong with it? And which part? Both
> Email::Simple & Email::MIME? Or only some subpart of it? And both
> getting and setting headers? Or only getting them?

What I meant was: we were talking about questions of API design, and you mo=
ved
to implementation, which I think is premature.

> Do not take me wrong, but to check that API is usable, you need to
> implement at least some POC and try to use it yourself. If it does not
> meet everything needed, then you need to rework it. And this is what now
> did.

I agree that you need to test an API to determine whether it is sufficient,=
 but
it's also possible to see something is insufficient before trying.  Since I
don't think the header_addrlist API is sufficient, it seems like implementa=
tion
is jumping the gun, to me.

> Look at my proposal just for first version and lets change parts which
> are not OK for you. I do not believe that everything is totally wrong.

Okay!

First, I think we should just leave Email::Simple alone.  In general, I thi=
nk
the cases for using Email::Simple are very few, and almost nobody should ev=
er
use it.  Giving it new and ostensibly MIME-related features seems unnecessa=
ry.
Having said that, I'm not going to look at the Email::Simple changes in dep=
th.
(We definitely don't want to make installing Email::Simple require loading
Email::Address::List::XS, I'll note.)

I think that ->format is probably not a great name choice, as it might exist
other places too easily.  For example, Email::Address has a ->format, but I
don't think it will be suitable for this, as it doesn't encode properly.  T=
his
is why I originally suggested something almost guaranteed not to clash, like
->as_mime_header.  We can assume that programmers won't have to call this v=
ery
often, only the innards of Email::MIME, so it's okay if it's a bit wordy.

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.

Primarily, I don't like the special weight given to the addrlist header.  W=
hile
it's likely to be the most common one, I think that implementing it as a
special case rather than an application of the general case, is going to le=
ad
to problems.  (Just yesterday I spent much of the day on DKIM, and it was c=
lear
that Authentication-Results and Domain-Signature could both usefully have
special objects.)

> [...]
> So easy extensible API needs to have one method which do that. Now I
> have only idea with something like this:
>=20
>  my $addrlist =3D $email->header_to_obj("Cc", "Email::Address::List::XS");
>=20
> That will convert header "Cc" to object Email::Address::List::XS and
> MIME decode parts which needs to be decoded.
>=20
> (Maybe class name could be optional and some mapping table for most
> common headers could be prepared)

I think this is all plausible.  The parts that are important to me are:

* objects working for all headers equally well
* a registry of common field-name-to-class-name mappings

> That method still needs to be know how to MIME decode object
> Email::Address::List::XS...

I'm not sure what you mean, here.  Do you mean that if we've stored a header
entry as an object that has an as-mime-encoded-string method, we also end up
needed a means to get it as-decoded-string?  I'm afraid I just don't unders=
tand
the sentence.

Your changes to Email::Simple don't store objects, but produce them on dema=
nd.
I'm thinking of:
https://github.com/rjbs/Email-Simple/compare/master...pali:master#diff-8816=
e211b9069c6bfa4cc4c82b7410b3R224

If we never *store* objects, but only produce them as requested, then I thi=
nk
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 object=
s,
  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

The downside is that if you call ->header_str(...) for something structured=
 and
there's no registered class for that field name, you get a less than stellar
answer.  Really, header_str becomes an odd method, because many headers are=
n't
meant to exist as unencoded single strings, but are structures.  Still, we =
can
fake it as needed, advising people to consider using object forms directly.

I think the way that header_addrlist and header_addrlist_raw behave is
confusing.  Rather than have two object representations, it seems that the =
data
should be represented as the same object, either way, and then data within =
it
should be asked for in encoded or decoded format.  That is: the header's raw
content is data that classes exist to interpret, access, and produce.  If we
generalized this to header_valueobj and header_valueobj_raw, I think it wou=
ld
be quite bizarre.

--=20
rjbs

--0F1p//8PRICkK4MW
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQEcBAEBAgAGBQJXy024AAoJEOYby6cMccU56t4H/ju1VQmSWh+L10yu9bI7zwvc
7hAllTHzqRPk0MxJpMZ80yPTov82iKfqF9iHIpnlqmjp0phf6r9h9GQjjOxLUyZO
Xd2hhh01yLxjh4C62exS1umu02IV6lpcYoKzmODoxtXU5cytUpAstA/WfQwOY7OZ
OMdIXZHDlX8XdKKGIUF5GzF5NYNbZtiRLsnfKpRA6NABWkfgKp/VNVD5cfOMHSJW
nlEJXEGfAlAaSTknmCXSEW1fgfa2qClI0uAbvZ4EGY5CSEUAJ/6dR0hd8aNUIeJS
3EuvPYVcVROpFIi4KMtS3SHdaVCCrlC6LQHQ4Whl+0hZZTUYt6K2Ihy3YYay9uE=
=9dIo
-----END PGP SIGNATURE-----

--0F1p//8PRICkK4MW--