Send email across all platforms using one interface

Overview

Build Status Scrutinizer Code Quality Code Coverage Latest Stable Version Join the chat at https://gitter.im/omnimail/omnimail

Send email across all platforms using one interface.

Table Of Content

  1. Requirements
  2. Installation
  3. Providers
  4. Email
  5. Mass Mailings
  6. Factory
  7. Exceptions
  8. Logging
  9. License

Requirements

This library uses PHP 5.6 and greater version.

Installation

It is recommended that you install the Omnimail library through composer. To do so, run the Composer command to install the latest stable version of Omnimail library.

composer require omnimail/omnimail

Providers

AmazonSES

Installation

To use the AmazonSES mailer class, you will need to install the daniel-zahariev/php-aws-ses library using composer.

composer require "daniel-zahariev/php-aws-ses:^0.9.2"

Usage

use Omnimail\Email;
use Omnimail\AmazonSES;

$mailer = new AmazonSES($accessKey, $secretKey, $region, $verifyPeer, $verifyHost, $signatureVersion);

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

Mailgun

Installation

To use the Mailgun mailer class, you will need to install the mailgun/mailgun-php library using composer. You do also need to install a HTTP client that sends messages. You can use any client that provided the virtual package php-http/client-implementation

composer require mailgun/mailgun-php php-http/guzzle6-adapter

Usage

use Omnimail\Email;
use Omnimail\Mailgun;

$mailer = new Mailgun($apiKey, $domain);

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

Mailjet

Installation

To use the Mailjet mailer class, you will need to install the mailjet/mailjet-apiv3-php library using composer.

composer require mailjet/mailjet-apiv3-php

Usage

use Omnimail\Email;
use Omnimail\Mailjet;

$mailer = new Mailjet($apikey, $apisecret);

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

Mandrill

Installation

To use the Mandrill mailer class, you will need to install the mandrill/mandrill library using composer.

composer require mandrill/mandrill

Usage

use Omnimail\Email;
use Omnimail\Mandrill;

$mailer = new Mandrill($apiKey);

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

Postmark

Installation

To use the Postmark mailer class, you will need to install the wildbit/postmark-php library using composer.

composer require wildbit/postmark-php

Usage

use Omnimail\Email;
use Omnimail\Postmark;

$mailer = new Postmark($serverApiToken);

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

Sendgrid

Installation

To use the Sendgrid mailer class, you will need to install the sendgrid/sendgrid library using composer.

composer require sendgrid/sendgrid

Usage

use Omnimail\Email;
use Omnimail\Sendgrid;

$mailer = new Sendgrid($apiKey);

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

SendinBlue

Installation

To use the SendinBlue mailer class, you will need to install the mailin-api/mailin-api-php library using composer.

composer require mailin-api/mailin-api-php

Usage

use Omnimail\Email;
use Omnimail\SendinBlue;

$mailer = new SendinBlue($accessKey);

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

SMTP

Installation

To use the SMTP mailer class, you will need to install the phpmailer/phpmailer library using composer.

composer require phpmailer/phpmailer

Usage

use Omnimail\Email;
use ShahariaAzam\SMTPMailer\SMTPMailer;

$mailer = new SMTPMailer("SMTP HOSTNAME", "SMTP USERNAME", "SMTP PASSWORD");

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

Gmail

Installation

To use the Gmail mailer class, you will need to install the phpmailer/phpmailer library using composer.

composer require phpmailer/phpmailer

Usage

use Omnimail\Email;
use Omnimail\Gmail;

$mailer = new Gmail("[email protected]", "password", []);

$email = (new Email())
    ->addTo('[email protected]')
    ->setFrom('[email protected]')
    ->setSubject('Hello, world!')
    ->setTextBody('Hello World! How are you?');

$mailer->send($email);

Email

An Email object implements the EmailInterface inteface. You can create your own Email class and send it to any mailer if it implements the EmailInterface inteface.

To

The To property of the email is for defining the recipients of the email. You can set multiple recipients.

$email = new Email();
$email->addTo('[email protected]', 'Recipient1 Name');
$email->addTo('[email protected]', 'Recipient2 Name');

From

The From property of the email is for defining the mailer of the email.

$email = new Email();
$email->setFrom('[email protected]', 'Sender Name');

CC

Like the To property, the CC property can have multiple recipients.

$email = new Email();
$email->addCc('[email protected]', 'Recipient1 Name');
$email->addCc('[email protected]', 'Recipient2 Name');

BCC

Like the To property, the BCC property can have multiple recipients.

$email = new Email();
$email->addBcc('[email protected]', 'Recipient1 Name');
$email->addBcc('[email protected]', 'Recipient2 Name');

Reply To

The Reply To property of the email is for defining the email that should receive responses.

$email = new Email();
$email->setReplyTo('[email protected]', 'Sender Name');

Subject

The Subject property of the email is for defining the subject of the email.

$email = new Email();
$email->setSubject('Hello, World!');

Text Body

The Text Body property of the email is for defining the text body of the email.

$email = new Email();
$email->setTextBody('This is plain text.');

HTML Body

The HTML Body property of the email is for defining the HTML body of the email.

$email = new Email();
$email->setHtmlBody('<h1>Hi!</h1><p>This is HTML!</p>');

Attachments

The Attachments property of the email is for joining attachments to the email.

Example using string as content

use Omnimail\Email;
use Omnimail\Attachment;

$attachment = new Attachment();
$attachment->setName('my_file.txt');
$attachment->setMimeType('text/plain');
$attachment->setContent('This is plain text');

$email = new Email();
$email->addAttachment($attachment);

Example using file path as content

use Omnimail\Email;
use Omnimail\Attachment;

$attachment = new Attachment();
$attachment->setMimeType('text/plain');
$attachment->setPath(__DIR__ . '/my_file.txt');

$email = new Email();
$email->addAttachment($attachment);

Inline attachments

use Omnimail\Email;
use Omnimail\Attachment;

$attachment = new Attachment();
$attachment->setPath(__DIR__ . '/image.png');
$attachment->setContentId('image.png');

$email = new Email();
$email->setHtmlBody('<p>Hello!</p><img src="cid:image.png">');
$email->addAttachment($attachment);

Factory

Alternatively, you can use the factory method to create a mailer. Consider the following example to create a AmazonSES mailer:

use Omnimail\Omnimail;

$mailer = Omnimail::create(Omnimail::AMAZONSES, ['accessKey' => $accessKey, 'secretKey' => $secretKey]);

Mass Mailings

The mass mailing component is for interacting with mass mailing providers. Currently the code focusses on data retrieval, but in future it should also define creating and sending mass mailings.

There are 2 functions currently described for the Mass mailings interface getMailings and getRecipients.

getMailings

    $mailer = Omnimail::create('Silverpop', array('credentials' => new Credentials(array('username' => $userName...)))->getMailings();
    $mailer->setStartTimeStamp(strtotime('7 days ago'));
    $mailer->setEndTimeStamp(strtotime('now'));
    // Instead of using set methods a Credentials object can be passed in ie.
    // Omnimail::create('Silverpop', array('credentials' => new Credentials(array('username' => $userName...)));
    // The advantage of using the Credentials object is that the object will not disclose
    // the credentials when var_dump or similar is called, helping to make the code
    // more secure.

    $mailings = $mailer->getResponse();
    for ($i = 0; $i < 15; $i++) {
      if (!$mailings->isCompleted()) {
        sleep(15);
      }
      else {
        foreach (\Omnimail\Common\Responses\BaseResponse $mailings as \Omnimail\Common\Responses\Mailing $mailing) {

           $detail => array(
             'subject' => $mailing→getSubject(),
             'external_identifier' => $mailing->getMailingIdentifier(),
             'name' => $mailing->getName(),
             'scheduled_date' => $mailing->getScheduledDate(),
             'start_date' => $mailing->getSendStartDate(),
             'number_sent' => $mailing->getNumberSent(),
             'body_html' => $mailing->getHtmlBody(),
             'body_text' => $mailing→getTextBody(),
             // Note that in the case of Silverpop these statistics are not retrieved by the
             // same api call. This is invisible to the calling function, and unless
             // stats are requested they are not retrieved.
             'number_bounced' => $mailing->getNumberBounces(),
             'number_opened_total' => $mailing->getNumberOpens(),
             'number_opened_unique' => $mailing->getNumberUniqueOpens(),
             'number_unsubscribed' => $mailing->getNumberUnsubscribes(),
             'number_suppressed' => $mailing->getNumberSuppressedByProvider(),
             // 'forwarded'
             'number_blocked' => $mailing->getNumberBlocked(),
             // 'clicked_total' => $stats['NumGrossClick'],
             'number_abuse_complaints' => $mailing->getNumberAbuseReports(),
            );
          }
      }
    }

getMailings

    $mailer = Omnimail::create('Silverpop')->getRecipients();
    $mailer->setUserName($userName);
    $mailer->setPassword($password);
    $mailer->setStartTimeStamp(strtotime('7 days ago'));
    $mailer->setEndTimeStamp(strtotime('now'));
    $mailer->setMailingIdentifier(123);

    $recipients = $mailer->getResponse();
    if (!$recipients->isCompleted()) {
      // sleep or exit & retry later.
    }

    foreach (\Omnimail\Responses\RecipientsResponse $recipients as \Omnimail\Responses\Recipient $$recipient) {

     $detail => array(
       'external_identifier' => $mailing->getMailingIdentifier(),
       'email' =>  $mailing->getEmail(),
       'provider_contact_id' => $mailing->getContactIdentifier(),
       'contact_id' => $mailing->GetContactReference(),
        // Const ACTION_SENT = ‘Sent’, ACTION_OPENED = ‘Open’, ...
       'action' => $mailing->getRecipientAction(),
       'timestamp' => getRecipientActionTimestamp(),
     );

Exceptions

Failures to send emails will throw exceptions.

Exceptions

  • Omnimail\Exception\Exception
  • Omnimail\Exception\EmailDeliveryException
  • Omnimail\Exception\InvalidRequestException
  • Omnimail\Exception\UnauthorizedException
  • Omnimail\Exception\MailerNotFoundException

To catch all exception, consider the following.

try {
    $mailer->send($email);
} catch (\Omnimail\Exception\Exception $e) {
    echo 'Something went wrong: ' . $e->getMessage();
}

To catch specific exceptions, consider the following.

try {
    $mailer->send($email);
} catch (\Omnimail\Exception\UnauthorizedException $e) {
    echo 'Your credentials must be incorrect';
} catch (\Omnimail\Exception\InvalidRequestException $e) {
    echo 'The request is badly formatted, check that all required fields are filled.';
} catch (\Omnimail\Exception\EmailDeliveryException $e) {
    echo 'The email did not go out.';
}

Logging

All mailers constructors take a PSR-3 compatible logger.

Email sent (including the email) are logged at INFO level. Errors (including the email) are reported at the ERROR level.

Example using Monolog

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Omnimail\Mailgun;

$logger = new Logger('name');
$logger->pushHandler(new StreamHandler('path/to/your.log', Logger::INFO));

$mailer = new Mailgun($apiKey, $domain, $logger);
$mailer->send($email);

License

Omnimail is licensed under The MIT License (MIT).

Comments
  • Proposal to make some improvements

    Proposal to make some improvements

    As this library is growing and developer are showing interest, it would be great if we can re-factor something (no new feature, improvement on rapid improvement).

    I would like to propose few points here:

    • We need to improve tests as much as possible to make sure everything is working properly after changes.

    • We can remove travis and use GitHub workflow for CI to code checks, tests, etc.

    • We shouldn't accept any PR without tests and pass the CI workflow

    • Development related tooling is not much available for php5.5. Also its not being maintained anymore. So to keep minimum compatibility to php5.6

    • Bug fix release we can make frequently but we need to focus on development branch for major release.

    • All PR must be submitted to development branch and we will merge to merge based on milestone. So it will reduce frequent release and give developers some resting time to upgrade for every PR.

    Most of the related changes has been prepared in my draft PR https://github.com/gabrielbull/omnimail/pull/46.

    I would like to know your feedback before making any decision.

    Also please feel free to add your own proposal.

    Thanks in advance.

    proposals 
    opened by shahariaazam 11
  • Switch to using annotation for expectedException.

    Switch to using annotation for expectedException.

    The annotation works on multiple php versions whereas the expectedException function is only php 6. In order to re-enable tests on earlier php we need to switch to this

    opened by eileenmcnaughton 9
  • Add mass mailing functions.

    Add mass mailing functions.

    I have been working on adding support for the retrieval of details about mass mailings and the actions taken by recipients of them. The principles I have been working off are that the calling code should need to know very little about the mailing provider code, and that the code should support get-on-demand, by which I mean that some details about mailings may require a different api call to retrieve them, and this should be retrieved when required by the Omnimail integration, without the calling code needing to know. I have based my approach on Omnipay, who I believe have done a good job doing this for payment processors.

    Per the Omnipay approach I have given each action a Request and a Response object. The logic here is that the Mailer method returns a Request Object. Various standardised properties can be set on the RequestObject and then when getResponse() is called it returns a response object. The response object represents multiple mailings, or recipients, and is an object that extends BaseResponse, which in turn extends the array object. Using an array object allows it to be iterated with a foreach, but also allows properties and methods directly on the response object.

    I have put code examples in the Readme. My extension is here https://github.com/eileenmcnaughton/omnimail-silverpop

    Some things I am still pondering

    1. one of the weaknesses of Omnipay (which I have taken much inspiration from) is the fact the calling code needs to know the names of the credentials fields. If the calling code is implementing multiple providers this can be a pain. I think maybe a setCredentials function might make sense, where incoming credentials would simply be numerically-indexed. The calling app still needs to store the credentials in order, but not know if they are apiKey or signature or userName etc.

    2. In the case of silverpop the getRecipients action is 2 part - it requests a download and then retrieves it. I added an isCompleted function so the code can loop around until it is ready. In this case if you wish to not have the php code sleeping & do it in 2 separate processes there are some parameters that are available & need to be used in the next process. I have used getRetrievalParameters to get these and setRetrievalParamters to set them on the next instance.

    opened by eileenmcnaughton 7
  • Tests

    Tests

    Added Amazon SES Error catching Added some basic tests for each package to catch errors when their details are incorrect Fixed Mailgun tmpfiles cleanup. it was trying to loop through an array that was a null value when an error occurred so i just made tmpfiles an empty array

    Any idea how you're going to do more complex testing (possibly using a Guzzle Mock Handler)?

    opened by bretto36 7
  • Backward Compatibility - Scalar type hinting is supported only from PHP >= 7.0

    Backward Compatibility - Scalar type hinting is supported only from PHP >= 7.0

    Here is the constructor of AmazonSES from https://github.com/gabrielbull/omnimail/blob/master/src/AmazonSES.php#L137

    public function __construct($accessKey = null, $secretKey = null, $host = self::AWS_US_EAST_1, $verifyPeer = true, $verifyHost = true, LoggerInterface $logger = null, string $signatureVersion = SimpleEmailService::REQUEST_SIGNATURE_V4)
    {
        $this->verifyPeer = $verifyPeer;
        $this->verifyHost = $verifyHost;
        $this->accessKey = $accessKey;
        $this->secretKey = $secretKey;
        $this->host = $host;
        $this->logger = $logger;
        $this->signatureVersion = $signatureVersion;
    }
    

    In the last argument string $signatureVersion = SimpleEmailService::REQUEST_SIGNATURE_V4. Scalary type hinting on argument is not supported in PHP5.5 as this library is supposed to support PHP5.5 too.

    It seems that in the recent PR https://github.com/gabrielbull/omnimail/pull/40 that changes were made. But it will break the backward compatibility for PHP5.5.

    We should fix it ASAP.

    bug amazonses-mailer 
    opened by shahariaazam 6
  • Roadmap....

    Roadmap....

    Hi,

    I was looking for something like this that took an Omnipay-style approach to Mail integration & this looks good. The only thing is .. there is no actual overlap between what your package is doing & what I am working on - I'm going to paste it up here anyway in case there is some synergy - as I feel like you have the starting point for more comprehensive integration with mailing providers.

    The way I expect my calling code to look is something like

    $mailingIntegration = new Omnimail::create('Silverpop', $credentials);
    $mailings = $mailingIntegration->getMailings(array('start_date' => '2017-01-01'));
    
    foreach ($mailings as $mailing) {
      $html = $mailing->getHtml();
      $subject = $mailing->getSubject();
      $text = $mailing->getText();
      // this is their unique ID
      $theirIdentifier = $mailing->getProviderIdentifier();
    
      $ourIdentifier = $mailing->getIndentifier();
      $name = $mailing->getName();
      $created_date = $mailing->getCreatedDate();
      $scheduled_date = $mailing->getScheduledDate();
    
      $numberSent = $mailing->getNumberSent();
      $numberDelivered = $mailing->getNumberDelivered();
        // e.g spam
      $numberBounced = $mailing->getNumberBounced();
      $numberBlocked = $mailing->getNumberBlocked();
      $numberUnsubscribe = $mailing->getNumberUnsubscribed();
      $numberComplaints = $mailing->getNumberAbuseReports();
      $numberOpens = $mailing->getNumberOpens();
      $numberUniqueOpens = $mailing->getNumberUniqueOpens();
      $numberClicks = $mailing->getNumberClicks();
      $numberUniqueClicks = $mailing->getNumberUniqueClicks();
    
      $bounces = $mailing->getBounces();
      foreach ($bounces as $bounce) {
        $recipient = $bounce->getRecipient();
        $ourIdentifier= $recipient->getIdentifier();
        // ie identifier for the provider
        $theirIdentifier = $recipient->getProviderIdentifier();
        $emailAddress = $recipient->getEmail();
        $bounceType = $bounce->getBounceType();
        
      }
    }
    
    opened by eileenmcnaughton 4
  • Future plans

    Future plans

    I'm wanting to check in on future plans for this extension.

    Currently the minimum php version is set to 5.6 and the current supported versions 8.0 and 8.1 are not being run under CI https://www.php.net/supported-versions.php. I would suggest that a minimum version of 7.2 (unsupported as of a year ago) or 7.3 (only just unsupported) would allow keeping up to date with packages and coding style and make it easier to add support for newer versions.

    I also have questions about functionality. The functionality gaps I'm hitting are

    • inability to set some parameters on smtp mailer - I did just now move my PR on that from the old repo to this one
    • wanting to extend the mass mailing functionality - eg. currently there are functions to retrieve recipient lists but not to create them. I can PR in some of this functionality if people are open to it but otherwise I probably need to think about other approaches in our codebase.
    opened by eileenmcnaughton 3
  • Add Factory methods

    Add Factory methods

    @eileenmcnaughton Continuity of PR #19

    Per the unit tests this adds the following factory pattern - discussedin #14

    This is based on the way the Omipay extension does it. You might not want to includete swiftmailer in the composer.json / in the factory test, but I wanted to demonstrate how this could work with packages that leveraged your packages, without them actually having to be in your package. Once again that is based on how Omnipay does it.

    enhancement 
    opened by gabrielbull 3
  • CI Improvement & Automation - Work in Progress

    CI Improvement & Automation - Work in Progress

    It's not ready yet to merge. Still work in progress .:)

    09 August 2020: It's now ready to merge after accepting proposal https://github.com/omnimail/omnimail/issues/47

    enhancement testing compatibility 
    opened by shahariaazam 2
  • Make parameters optional on constructor classes.

    Make parameters optional on constructor classes.

    This is part of the work to add factory methods & addresses php 7 test failures per https://github.com/gabrielbull/omnimail/pull/20#issuecomment-295787131

    opened by eileenmcnaughton 2
  • Add BaseTestClass & set as a dependency.

    Add BaseTestClass & set as a dependency.

    From the recent upgrade to php 7 I can see that every file had to be changed to reflect the phpunit version. By extending a class we can put that change in one place.

    I'm actually working on php 5.6 so this allows me to run the tests on that version with a low level of tinkering

    opened by eileenmcnaughton 2
  • Add support for contact management - specifically gdpr functions

    Add support for contact management - specifically gdpr functions

    I'm going to add a contact interface that allows the functions

    privacyInformationRequest privacyInformationDelete

    • these will call actions that providers have created for GDPR purposes
    enhancement 
    opened by eileenmcnaughton 0
  • SendGrid Bad Gateway

    SendGrid Bad Gateway

    I'm getting a bad gateway error when sending an e-mail with SendGrid. I've confirmed that:

    1. The error occurs with the example code provided in README.md
    2. The error doesn't occur when using the bare SendGrid library.
    3. The error occurs on multiple machines.

    I can reproduce as follows:

    $ composer require sendgrid/sendgrid
    $ composer require omnimail/omnimail
    
    /* test1.php */
    <?php
    require_once (__DIR__ . '/vendor/autoload.php');
    
    use Omnimail\Email;
    use Omnimail\Sendgrid;
    
    $mailer = new Sendgrid(MY_REAL_LIFE_SG_KEY);
    
    $email = (new Email())
        ->addTo('[email protected]')
        ->setFrom('[email protected]')
        ->setSubject('Hello, world!')
        ->setTextBody('Hello World! How are you?');
    
    $mailer->send($email);
    
    /* test2.php */
    <?php
    require_once (__DIR__ . '/vendor/autoload.php');
    
    $from = new SendGrid\Email("Example User", "[email protected]");
    $subject = "Sending with SendGrid is Fun";
    $to = new SendGrid\Email("Example User", "[email protected]");
    $content = new SendGrid\Content("text/plain", "and easy to do anywhere, even with PHP");
    $mail = new SendGrid\Mail($from, $subject, $to, $content);
    
    $sg = new \SendGrid(MY_REAL_LIFE_SG_KEY);
    
    $response = $sg->client->mail()->send()->post($mail);
    echo $response->statusCode();
    print_r($response->headers());
    echo $response->body();
    
    $ php test1.php
    PHP Fatal error:  Uncaught exception 'Omnimail\Exception\InvalidRequestException' in C:\Users\jschilz\test\vendor\omnimail\omnimail\src\Sendgri
    d.php:137
    Stack trace:
    #0 C:\Users\jschilz\test\test1.php(15): Omnimail\Sendgrid->send(Object(Omnimail\Email))
    #1 {main}
      thrown in C:\Users\jschilz\test\vendor\omnimail\omnimail\src\Sendgrid.php on line 137
    
    Fatal error: Uncaught exception 'Omnimail\Exception\InvalidRequestException' in C:\Users\jschilz\test\vendor\omnimail\omnimail\src\Sendgrid.php
     on line 137
    
    Omnimail\Exception\InvalidRequestException:  in C:\Users\jschilz\test\vendor\omnimail\omnimail\src\Sendgrid.php on line 137
    
    Call Stack:
        0.0002     124920   1. {main}() C:\Users\jschilz\test\test1.php:0
        0.0056     425304   2. Omnimail\Sendgrid->send() C:\Users\jschilz\test\test1.php:15
    

    I put some debugging statements inside SendGrid.php to determine that SendGrid is returning a 502 Bad Gateway response.

    $ php test2.php
    202Array
    (
        [0] => HTTP/1.1 202 Accepted
        [1] => Server: nginx
        [2] => Date: Tue, 23 Jan 2018 00:26:40 GMT
        [3] => Content-Type: text/plain; charset=utf-8
        [4] => Content-Length: 0
        [5] => Connection: keep-alive
        [6] => X-Message-Id: AFEhnCqnT46tLy-1FAdm-A
        [7] => Access-Control-Allow-Origin: https://sendgrid.api-docs.io
        [8] => Access-Control-Allow-Methods: POST
        [9] => Access-Control-Allow-Headers: Authorization, Content-Type, On-behalf-of, x-sg-elas-acl
        [10] => Access-Control-Max-Age: 600
        [11] => X-No-CORS-Reason: https://sendgrid.com/docs/Classroom/Basics/API/cors.html
        [12] =>
        [13] =>
    )
    

    I can work to trouble shoot this tomorrow, but I thought I'd post the issue tonight incase the solution is obvious to you. (:

    bug sendgrid-mailer compatibility 
    opened by JASchilz 1
  • Feature proposal: logging only mailer

    Feature proposal: logging only mailer

    For debugging and development purposes, it would be helpful for me to have a mailer which does not send any emails. Instead, it would implement only the logging features of a mailer. The calling code could provide this mailer a logger which logs to the console, or to a file, etc.

    I would propose to call this mailer class NoMail, implementing the MailerInterface. Per your spec, it would log emails at info level.

    If you concur, I'll submit a pull request. Otherwise, please close. (:

    enhancement testing feature-requests 
    opened by JASchilz 3
Releases(0.4.0)
Owner
Omnimail
Omnimail
Magento 2 Email Catcher or Email Logger Module.

Magento 2 Module Experius email catcher / - logger

Experius 49 Dec 16, 2021
SendPortal - Open-source self-hosted email marketing, subscriber and list management, email campaigns and more

SendPortal includes subscriber and list management, email campaigns, message tracking, reports and multiple workspaces/domains in a modern, flexible and scalable application.

Mettle 1.2k Jan 4, 2023
Cross-language email validation. Backed by a database of over 38 000 throwable email domains.

Cross-language temporary (disposable/throwaway) email detection library. Covers 38038+ fake email providers.

Francois-Guillaume Ribreau 1.4k Jan 9, 2023
Small PHP library to valid email addresses using a number of methods.

Email Validator Small PHP library to valid email addresses using a number of methods. Features Validates email address Checks for example domains (e.g

James Jackson 154 Dec 31, 2022
Library for using online Email providers

Stampie Stampie have been moved to the "Flint" organization in order to get a better collaborative flow. Stampie is a simple API Wrapper for different

Henrik Bjørnskov 32 Oct 7, 2020
Library for using online Email providers

Stampie Stampie is a simple API Wrapper for different email providers such as Postmark and SendGrid. It is very easy to use and to integrate into your

Stampie 288 Dec 31, 2022
Fetch is a library for reading email and attachments, primarily using the POP and IMAP protocols

Fetch Fetch is a library for reading email and attachments, primarily using the POP and IMAP protocols. Installing N.b. A note on Ubuntu 14.04 (probab

Tedious Developments 501 Jan 4, 2023
Queue, preview and and send emails stored in the database.

Codeigniter4 email queue Queue, preview and and send emails stored in the database. This package provides an interface for creating emails on the fly

null 3 Apr 12, 2022
Send beautiful HTML emails with Laravel

Beautymail for Laravel Beautymail makes it super easy to send beautiful responsive HTML emails. It's made for things like: Welcome emails Password rem

null 1.1k Jan 2, 2023
SlmMail is a module that integrates with various third-parties API to send mails. Integration is provided with the API of those services

SlmMail is a module that integrates with various third-parties API to send mails. Integration is provided with the API of those services

Webador 107 Dec 14, 2022
A Laravel package to check if you can send e-mail through a given mailserver in name of a given e-mail address

A Laravel package to check if you can send e-mail through a given mailserver in name of a given e-mail address Mail spf checker A Laravel package to c

Dieter Coopman 110 Dec 16, 2022
Mail Api for fetch or send mails

flux-mail-api Mail Api for fetch or send mails Installation Native Download RUN (mkdir -p /%path%/libs/flux-mail-api && cd /%path%/libs/flux-mail-api

null 2 Dec 12, 2022
The classic email sending library for PHP

PHPMailer – A full-featured email creation and transfer class for PHP Features Probably the world's most popular code for sending email from PHP! Used

PHPMailer 19k Jan 1, 2023
PHP library for parsing plain text email content.

EmailReplyParser EmailReplyParser is a PHP library for parsing plain text email content, based on GitHub's email_reply_parser library written in Ruby.

William Durand 606 Dec 8, 2022
Mail sending module for Mezzio and Laminas MVC with support for file attachment and template email composition

This module provides an easy and flexible way to send emails from Mezzio and Laminas MVC applications (formerly known as Zend Expressive and Zend MVC). It allows you to pre-configure emails and transports, and then send those emails at runtime.

null 82 Jan 16, 2022
Omnisend: Ecommerce Email Marketing and SMS Platform

Omnisend Omnisend: Ecommerce Email Marketing and SMS Platform Version v1.x Support all PHP Version >=5.6 v2.x Support all PHP Version >=7.0 Installati

Hung Nguyen 3 Jan 6, 2022
Sending Email via Microsoft Exchange Web Services made Easy!

Send Mail via Exchange Web Services! Sending Email via Microsoft Exchange Web Services (EWS) made easy! Installation Install via Composer composer req

Raju Rayhan 19 Jul 19, 2022
Mailcoach is a self-hosted email list manager - in a modern jacket.

Welcome to Mailcoach Mailcoach is a self-hosted email list manager - in a modern jacket. It features: Subscribers and lists management Subscribe, doub

Spatie 3 Jan 31, 2022
An AngularJS / Laravel app - Keyword Based Email forwarder | read/write emails through IMAP

@MailTree Simple mail forwarder. Based on the specific email body/subject keywords forward mails to the list of predefined users. Install Imap Install

Dren Kajmakchi 4 Aug 21, 2018