We used to have simple mailto: links to provide users a simple way to open a new draft email with the relevant emails directly filled in.
The issue is that there is a limit to the length of href supported by such links (about 2000 chars), and sometimes we'll need more than that.
So to avoid this issue, I'm shifting to a server-side solution by building a new DraftEmail
and just send it in my Response
after a .toString()
.
It works fine as long as the emails are provided in the 'to' and 'cc' fields, but the 'bcc' field doesn't work.
It seems to be on purpose :
https://github.com/symfony/symfony/blob/7.3/src/Symfony/Component/Mime/DraftEmail.php
From what I understand, it seems related to the fact that the bcc should not be in the message but in the envelope. Ok, but then what would be a simple way to do what I'm attempting to do? Because as far as I understand, the envelope is used to send the message, but I don't want to send the message, I just want to create it, the sending is handled by the email client.
Another issue is that unlike mailto: links, a DraftEmail doesn't seem to add the signature of the user, I assume it's because it's an external file and not a new message or a reply, but that's an issue as well.
Are there alternatives in symfony to mailto: links that does the same thing as far as signatures and bcc recipients are concerned, while not having the length limitation?
Thank you for your help
Create a custom DraftEmail
class that overrides getPreparedHeaders
to retain Bcc
.
use Symfony\Component\Mime\DraftEmail;
use Symfony\Component\Mime\Header\Headers;
class CustomDraftEmail extends DraftEmail
{
public function getPreparedHeaders(): Headers
{
$headers = clone $this->getHeaders();
if (!$headers->has('MIME-Version')) {
$headers->addTextHeader('MIME-Version', '1.0');
}
// Do NOT remove Bcc headers
return $headers;
}
}
Then use the CustomDraftEmail
class to create a draft email and include Bcc
recipients in the MIME message.
use App\Mail\CustomDraftEmail;
use Symfony\Component\HttpFoundation\Response;
$email = (new CustomDraftEmail())
->to('recipient@example.com')
->cc('cc@example.com')
->bcc('bcc@example.com')
->subject('Test Draft Email')
->text('This is the email body.');
$response = new Response($email->toString());
$response->headers->set('Content-Type', 'text/plain'); // Adjust based on delivery method
return $response;
------ Edits
This may be not matching your exact needs but, this is how we fixed the issue.
Like @chris-haas pointed it out, this solution's limitation is a lack of automatic signatures. We mitigated it by appending a placeholder signature to the email body programmatically. (Another alternative can be to Instruct users to add their signature manually after opening the .eml file in their email client):
Create a controller :
use App\Mail\CustomDraftEmail;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class EmailController extends AbstractController
{
public function createDraftEmail(): Response
{
$email = (new CustomDraftEmail())
->to('recipient@example.com')
->cc('cc@example.com')
->bcc('bcc@example.com')
->subject('Test Draft Email')
->text("The email body.\n\n-- \nYour Name"); // Here the signature is added
$response = new Response($email->toString());
$disposition = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
'draft-email.eml'
);
$response->headers->set('Content-Type', 'message/rfc822');
$response->headers->set('Content-Disposition', $disposition);
return $response;
}
}
When the user clicks a link to this endpoint, their browser will download a .eml
file.