Pular para o conteúdo principal

Exceptions

MailWrapper defines several exception classes to handle different error conditions. All exceptions are in the ByJG\Mail\Exception namespace.

Exception Hierarchy​

All MailWrapper exceptions extend standard PHP exceptions, allowing you to catch them individually or as a group.

\Exception
├── InvalidEMailException
├── InvalidMailHandlerException
├── InvalidMessageFormatException
├── MailApiException
└── ProtocolNotRegisteredException

Exception Types​

InvalidEMailException​

Thrown when email validation fails.

Common causes:

  • Missing sender address
  • Missing recipient address
  • Invalid email format

Example:

use ByJG\Mail\Exception\InvalidEMailException;

try {
$envelope = new \ByJG\Mail\Envelope();
// No from or to addresses set
$mailer->send($envelope);
} catch (InvalidEMailException $e) {
echo "Email validation failed: " . $e->getMessage();
// Output: "Destination Email was not provided"
}

ProtocolNotRegisteredException​

Thrown when trying to create a mailer for an unregistered protocol scheme.

Common causes:

  • Forgetting to register a wrapper with MailerFactory::registerMailer()
  • Using an invalid or misspelled scheme in the connection string
  • Wrapper not installed or available

Example:

use ByJG\Mail\Exception\ProtocolNotRegisteredException;

try {
// Forgot to register the SMTP wrapper
$mailer = \ByJG\Mail\MailerFactory::create('smtp://user:pass@host');
} catch (ProtocolNotRegisteredException $e) {
echo "Protocol error: " . $e->getMessage();
// Output: "Protocol not found/registered!"
}

Solution:

// Register the wrapper before creating the mailer
\ByJG\Mail\MailerFactory::registerMailer(\ByJG\Mail\Wrapper\PHPMailerWrapper::class);
$mailer = \ByJG\Mail\MailerFactory::create('smtp://user:pass@host');

InvalidMailHandlerException​

Thrown when trying to register an invalid wrapper class.

Common causes:

  • Registering a class that doesn't implement MailWrapperInterface
  • Passing a non-existent class name

Example:

use ByJG\Mail\Exception\InvalidMailHandlerException;

try {
\ByJG\Mail\MailerFactory::registerMailer(\MyApp\InvalidClass::class);
} catch (InvalidMailHandlerException $e) {
echo "Registration error: " . $e->getMessage();
// Output: "Class not implements ConnectorInterface!"
}

InvalidMessageFormatException​

Thrown when the message format is invalid or incomplete.

Common causes:

  • Invalid message structure
  • Missing required fields
  • Malformed content

Example:

use ByJG\Mail\Exception\InvalidMessageFormatException;

// This exception might be thrown by custom wrappers with additional validation
try {
// Some wrapper that validates subject is not empty
$mailer->send($envelope);
} catch (InvalidMessageFormatException $e) {
echo "Message format error: " . $e->getMessage();
}

MailApiException​

Thrown when an email API returns an error.

Common causes:

  • Invalid API credentials
  • API rate limiting
  • Network connectivity issues
  • Service outages
  • Invalid email addresses rejected by the API

Example:

use ByJG\Mail\Exception\MailApiException;

try {
$mailer = \ByJG\Mail\MailerFactory::create('mailgun://[email protected]');
$mailer->send($envelope);
} catch (MailApiException $e) {
echo "API error: " . $e->getMessage();
// Might include API-specific error details
}

Exception Handling Best Practices​

Catch Specific Exceptions​

Handle different exception types appropriately:

use ByJG\Mail\Exception\{
InvalidEMailException,
ProtocolNotRegisteredException,
MailApiException
};

try {
$mailer = \ByJG\Mail\MailerFactory::create($connection);
$result = $mailer->send($envelope);

} catch (InvalidEMailException $e) {
// Validation error - fix the envelope data
error_log("Invalid email configuration: " . $e->getMessage());

} catch (ProtocolNotRegisteredException $e) {
// Configuration error - register the protocol
error_log("Missing protocol registration: " . $e->getMessage());

} catch (MailApiException $e) {
// API error - might be temporary, consider retrying
error_log("Mail service API error: " . $e->getMessage());

} catch (\Exception $e) {
// Catch-all for unexpected errors
error_log("Unexpected error: " . $e->getMessage());
}

Validate Before Sending​

Validate the envelope before attempting to send:

$envelope = new \ByJG\Mail\Envelope();

// Validate manually if needed
if (empty($envelope->getFrom())) {
throw new \ByJG\Mail\Exception\InvalidEMailException('From address required');
}

if (count($envelope->getTo()) === 0) {
throw new \ByJG\Mail\Exception\InvalidEMailException('At least one recipient required');
}

Logging and Debugging​

Include context in error handling:

try {
$result = $mailer->send($envelope);

if (!$result->success) {
error_log(sprintf(
'Failed to send email to %s: %s',
implode(', ', $envelope->getTo()),
'Unknown error'
));
}

} catch (\Exception $e) {
error_log(sprintf(
'Exception sending email to %s: %s - %s',
implode(', ', $envelope->getTo()),
get_class($e),
$e->getMessage()
));

// Optionally include stack trace in development
if (DEBUG_MODE) {
error_log($e->getTraceAsString());
}
}

Retry Logic​

Implement retry logic for transient failures:

use ByJG\Mail\Exception\MailApiException;

function sendWithRetry($mailer, $envelope, $maxAttempts = 3): bool
{
$attempt = 0;

while ($attempt < $maxAttempts) {
try {
$result = $mailer->send($envelope);
return $result->success;

} catch (MailApiException $e) {
$attempt++;

if ($attempt >= $maxAttempts) {
throw $e;
}

// Exponential backoff
sleep(pow(2, $attempt));
}
}

return false;
}

Graceful Degradation​

Consider fallback mechanisms:

$primaryMailer = \ByJG\Mail\MailerFactory::create('mailgun://key@domain');
$fallbackMailer = \ByJG\Mail\MailerFactory::create('smtp://user:pass@host:587');

try {
$result = $primaryMailer->send($envelope);
} catch (\Exception $e) {
error_log('Primary mailer failed, using fallback: ' . $e->getMessage());
try {
$result = $fallbackMailer->send($envelope);
} catch (\Exception $e2) {
error_log('Fallback mailer also failed: ' . $e2->getMessage());
throw $e2;
}
}