Coder Social home page Coder Social logo

genkgo / mail Goto Github PK

View Code? Open in Web Editor NEW
401.0 14.0 21.0 798 KB

Library to send e-mails over different transports and protocols (like SMTP and IMAP) using immutable messages and streams. Also includes SMTP server.

Home Page: https://mail.readthedocs.io/

License: Other

PHP 99.57% HTML 0.43%
mail e-mail php mime immutable value-object smtp queue redis imap

mail's People

Contributors

emielbruijntjes avatar frederikbosch avatar gwendolenlynch avatar jakejohns avatar k00ni avatar meirbon avatar mpyw avatar photodude avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mail's Issues

Too many constructors

If we

  • include name in Address,
  • include multiple addresses in AddressList,

we need to write many constructors.

$message = $message
    ->withHeader(new From(new Address(new EmailAddress('[email protected]', '三浦')))
    ->withHeader(new Subject('Hello World'))
    ->withHeader(new To(new AddressList([
        new Address(new EmailAddress('[email protected]'), '木村'),
        new Address(new EmailAddress('[email protected]'), '鈴木'),
    ])));

So more static helper methods should be provided on From and To.

$message = $message
    ->withHeader(From::fromEmailAddressAndName('[email protected]', '三浦'))
    ->withHeader(new Subject('Hello World'))
    ->withHeader(To::fromMultipleRecipients([['[email protected]', '木村'], ['[email protected]', '鈴木']]));

Deeply structured classes have powerful robustness, however, they seem like Java way. It's not suitable for PHP. So I suggest providing more casual interfaces.

Consider renaming factories

When developing this library, I really had a hard time picking the right names for the right jobs.

Especially the name FormattedMessageFactory is controversial. It is a factory in a sense that is producing messages: like it drops messages from the assembly line. Therefore I chose the name.

However, I also read people rather see it as a builder. That also makes sense. Maybe it makes more sense. Since the library is already in stable state, however, I will only consider changing the name in a new major release.

Tests for formats and attachments

One thing most other mail libraries are really poor at is integrating attachments that are not text/plain, text/html or one of the image/* mime-types like for example ical / vcard.

It'd be really nice to see tests for that. Is it something you feel is outside of library need / support?

Possible error in EmailAddress

While I looking at the code I ran into the EmailAddress::equals() method. The method expect an EmailAddress as first parameter and use this to read the property called address ($address->address), but this property has private visibility. Probably submit a PR for that.

Add JMAP support (as an alternative to IMAP + SMTP, and later to CardDAV/CalDAV)

"JMAP is intended to be a new standard for email clients to connect to
mail stores. It therefore intends to primarily replace IMAP + SMTP
submission. It is also designed to be more generic such that it can be
extended with contacts, calendars in the future (replacing
CardDAV/CalDAV). It does not replace MTA-to-MTA SMTP transmission."

http://jmap.io/

You may wonder "Who uses or supports it?"

Cyrus IMAP and Apache James are the notable ones here:
http://jmap.io/software.html
https://cyrusimap.org/imap/developer/jmap.html

OpenPaaS is an open source Entreprise Social Platform which is led by
LINAGORA (which has more than 150 employees)
https://linagora.com/
http://www.open-paas.org

OpenPaaS is using Apache James. And you can see JMAP used in the code:
https://github.com/linagora/openpaas-esn/search?utf8=%E2%9C%93&q=jmap&type=

In this video: https://www.youtube.com/watch?v=2QZIi3EO6rQ , Benoit
Tellier explains why they decided to invest in James and JMAP (among
other things). LINAGORA has 5 full time employees which are devoted to
the project.

Why LINAGORA picked JMAP:
https://medium.com/linagora-engineering/you-cant-do-imap-in-the-browser-can-you-208838b0ba17
https://medium.com/linagora-engineering/openpaas-newsletter-march-2018-c0a3e469e83e
https://medium.com/linagora-engineering/openpaas-is-out-773704eadfbc

FastMail started this initiative:
"JMAP is FastMail's protocol with the warts removed. We leverage
existing standards like HTTP, JSON, and native push channels on
platforms which have them - making it easy for developers to work with."
https://blog.fastmail.com/2017/12/08/fastmail-at-ietf/
https://blog.fastmail.com/2016/12/22/cyrus-development-and-release-plans/
https://blog.fastmail.com/2016/12/12/why-we-contribute/
https://blog.fastmail.com/2016/12/09/jmap-test-suite/
https://blog.fastmail.com/2015/12/23/the-jmap-momentum-builds/
https://blog.fastmail.com/2015/08/11/an-open-source-jmap-proxy-javascript-library-and-webmail-demo/
https://blog.fastmail.com/2014/12/23/jmap-a-better-way-to-email/

Roundcube Next also plans to support JMAP.
https://github.com/search?q=org%3Aroundcube-next+jmap&type=Code

Thanks!

A request for help and an example of SearchCommand

Hello
Could you help by sharing an example using SearchCommand with for example DateCriterion and FlagCriterion returning an email list similar to imap_fetch_overview or any, similar to /example/imap-client-fetch.php?

In addition, I noticed trying to use:
$query = (new Query())->with(DateCriterion::since(new \DateTimeImmutable('2019-10-10')));
that in response I have
["line": "Genkgo\Mail\Protocol\Imap\Response\TaggedResponse": private] => string (87) "BAD Error in IMAP command SEARCH: Invalid search date parameter (0.001 + 0.000 secs). "
If I'm using $searched = imap_search($imap_stream, "SINCE 10-Oct-2019"); I have the expected response with a list of found emails.

Thank you for your help
Jacek

UTF-8, invalid characters as a result of AlternativeText

Hello
when I use UTF-8 and

$ message = (new FormattedMessageFactory())
                 ->withHtml(<p>zażółć gęślą jaźń</p>) ...

I have invalid characters in alternative text.
The problem is probably in AlternativeText::fromHtml($html) which uses: DOMDocument->loadHTML() which recodes characters.
regards

Long Japanese subject fails to decode on some mailers

Hello.

When I send an email with a long subject such as "あいうえおかきくけこさしすせそたちつてと", some mailers fail to decode.
The Subject header is as follows.

Subject:
 =?UTF-8?B?44GC44GE44GG44GI44GK44GL44GN44GP44GR44GT44GV44GX44GZ44Gb
 44Gd44Gf44Gh44Gk44Gm44Go?=

It seems that it can be decoded normally by enclosing each line as shown below.

Subject:
 =?UTF-8?B?44GC44GE44GG44GI44GK44GL44GN44GP44GR44GT44GV44GX44GZ44Gb?=
 =?UTF-8?B?44Gd44Gf44Gh44Gk44Gm44Go?=

Is it possible to fix this?

Best regards.

About the encoding of AlternativeText

Hello.

Currently, Base64 is specified as the encoding of AlternativeText, but I would like to change it to encode with 8bit.
As a test, I added withHeader(new ContentTransferEncoding("8bit")), but the base64-encoded character string was displayed as it was in the body.
Is there any way?

Best regards.

Buffing the initial readme documentation

I've worked through it, but the readme I think could use more verbosity. For example it says "Send message quick and easy" then has a code sample where the classes are referenced flatly without their namespace paths, nor the use statements required to make them work flatly as shown in the readme.

image

I only nag about this because I feel your classes are super duper maybe borderline overly spread out, in non obvious ways. To get these I ended up having to fallback to the github repo search.

Parsing addresses

Hello Frederik,

The existing PHP mail libraries are not good, so I can see the point of writing a new one. But I took the liberty to run some test input that we use for our software through your library, and you might want to spend some extra time on it. Parsing email addresses is painful, especially if you want to be fully RFC 2822 compatible. I can give you some extra input once you have tackled this :)

Cheers,

Emiel

<?php

require_once __DIR__ . "/src/EmailAddress.php";

try
{
    $address = new Genkgo\Mail\EmailAddress('"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com');

    echo("localpart: ".$address->getLocalPart()."\n");
    echo("domain: ".$address->getDomain()."\n");

}
catch (Exception $exception)
{
    echo("valid address not recognized\n");
}

$address1 = new Genkgo\Mail\EmailAddress("address(withcomment)@example.com");
$address2 = new Genkgo\Mail\EmailAddress("[email protected]");

echo("localpart 1: ".$address1->getLocalPart()."\n");
echo("domain 1: ".$address1->getDomain()."\n");
echo("localpart 2: ".$address2->getLocalPart()."\n");
echo("domain 2: ".$address2->getDomain()."\n");

// we expect the addresses to be similar, because comments should be ignored
if ($address1->equals($address2)) echo("yes they are equal!\n");
else echo("two identical addresses are not considered equal\n");

How to add attachments to PlainTextMessage

Hello.

I started using this library.
But there is one thing I don't understand.
I am composing a plain text message with "PlainTextMessage".
How can I add an attachment to this message?
"withAttachment" doesn't seem to be available in "PlainTextMessage".
If there is any good way, I would appreciate any advice.

Best regards.

Security audit

Preferably this code base receives a code review by a security expert.

ContentID enhancement

Currently ContentID is just a simple data container object. I think it needs the following features at least:

  1. When it is constructed:
  • It should be validated as url-addr-spec
  1. When it is represented as a header:
  • It should be enclosed with < and >
  • Its domain-part should be idn-encoded
  1. When it is represended as a CID-URL:
  • It should be prefixed with cid:
  • Its local-part should be percent-encoded
  • Its domain-part should be idn-encoded

However, it may break backward compatibility. To avoid it, static helper method is preferred.

$contentId = ContentID::fromUrlAddress("画像01@example.みんな"); // equivalent to new ContentID("<画像[email protected]>")

// external interfaces for building HTML
$contentId->getCidUrl(); // returns "cid:%E7%94%BB%E5%83%[email protected]"
$embeddedImage->getContentId()->getCidUrl();  // returns "cid:%E7%94%BB%E5%83%[email protected]"

Citations from RFC 2392:

   The URLs take the form

     content-id    = url-addr-spec

     message-id    = url-addr-spec

     url-addr-spec = addr-spec  ; URL encoding of RFC 822 addr-spec

     cid-url       = "cid" ":" content-id

     mid-url       = "mid" ":" message-id [ "/" content-id ]
 A "cid" URL is converted to the corresponding Content-ID message
   header [MIME] by removing the "cid:" prefix, converting the % encoded
   character to their equivalent US-ASCII characters, and enclosing the
   remaining parts with an angle bracket pair, "<" and ">".  For
   example, "cid:foo4%[email protected]" corresponds to

     Content-ID: <foo4%[email protected]>

   Reversing the process and converting URL special characters to their
   % encodings produces the original cid.

(I think the example is wrong; Content-ID: <foo4%[email protected]> seems to be correct)

I'm afraid that I'm not so familiar with RFC details...

Currently charset = us-ascii, how to set another one?

Hi, when checking the generated mail message manually, i discovered you using us-ascii as character set.

Example:

Subject: subject
From: sender name <[email protected]>
Reply-To: [email protected]
To: [email protected]
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary=GenkgoMailV2Part792e4450d62c

This is a multipart message in MIME format.

--GenkgoMailV2Part792e4450d62c
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

plain text

--GenkgoMailV2Part792e4450d62c
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

html text
--GenkgoMailV2Part792e4450

I was wondering how to change that? Also, could i run into UTF-8 related problems with that?

Angle brackets by default in Content-ID and Message-ID headers

Hello.

I would suggest using angle brackets in values of the Content-ID and Message-ID headers by default (auto addition in value).

Without angle brackets, image cannot be displayed, even if it does not contain special characters.

Example:

$logo = 'logotype.jpg';
$htmlBody = '<html><body><img src="cid:logotype"></body></html>';

$message = (new MessageBodyCollection($htmlBody))
	->withEmbeddedImage(new EmbeddedImage(
		new StringStream(file_get_contents($logo)),
		basename($logo),
		new ContentType('image/jpeg'),
		new ContentID('logotype')
	))
	->createMessage()
	->withHeader(new Subject('Привет мир'))
	->withHeader(From::fromAddress('[email protected]', 'Mail.ru'))
	->withHeader(To::fromSingleRecipient('[email protected]', 'Виталий'))
;

$transport = new PhpMailTransport(EnvelopeFactory::useExtractedHeader());

$transport->send($message);

But if we replace on that:

new ContentID('<logotype>')

It works.

Tested on CentOS (core Linux 2.6.32-042stab123.9 #1 SMP Thu Jun 29 13:01:59 MSK 2017 x86_64 GNU/Linux), PHP 7.2.8 (NTS) and Gmail.

An example of the link example/transport-smtp.php did not check, but I can assume that it is also not working in withEmbeddedImage method.

Thanks.

PHP 8+ support

Hello
On PHP 8.0.3 when I do composer require genkgo/mail

I get an error message:

[InvalidArgumentException]
Package genkgo/mail has a PHP requirement incompatible with your PHP version, PHP extensions and Composer version

Can you please update the package to install on PHP 8.0 systems?

Support internationalized email addresses (RFC 6530)

Unicode characters are allowed in email addresses. It looks like you do handle Unicode in domains but not in the local part. In any case, it's not mentioned in the README, so here we are. If it is supported (and to what extent), you probably should mention it there.

ssl custom context stream options

I do not see a way to add custom context stream options, for example
verify_peer, verify_peer_name and allow_self_signed
Is it possible?

Server class not correctly handling unknown SMTP commands

Test case

  • Note the missing DATA capability
$backend = new DevNullBackend();
$spam = new ForbiddenWordSpamScore([], 0);
$cap = [
    new MailFromCapability(),
    new RcptToCapability($backend),
];

$server = new Server(new PlainTcpConnectionListener('localhost', 2525), $cap, 'localhost');
$server->start();

Result

PHP Fatal error:  Uncaught TypeError: Return value of Genkgo\Mail\Protocol\AbstractConnection::receive() must be of the type string, boolean returned in [..]/src/Protocol/AbstractConnection.php:115
Stack trace:
#0 [..]/src/Protocol/AppendCrlfConnection.php(65): Genkgo\Mail\Protocol\AbstractConnection->receive()
#1 [..]/src/Protocol/TrimCrlfConnection.php(62): Genkgo\Mail\Protocol\AppendCrlfConnection->receive()
#2 [..]/src/Protocol/Smtp/Server.php(63): Genkgo\Mail\Protocol\TrimCrlfConnection->receive()
#3 [..]/test-server.php(27): Genkgo\Mail\Protocol\Smtp\Server->start()
#4 {main}
  thrown in [..]/src/Protocol/AbstractConnection.php on line 115

Additional Details

The return value of fgets in \Genkgo\Mail\Protocol\AbstractConnection::receive() is not checked for a boolean response, and an exception thrown. As the function is type hinted as string, things go 💥

A similar exception to the one thrown in send(), e.g. CannotReadFromStreamException, might be appropriate but still won't cover the handling in the server class itself

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.