-
-
Notifications
You must be signed in to change notification settings - Fork 257
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for adding attachments as LinkedResources in MailMessage #376
Comments
@jamesmh thoughts? |
@jamesmh did this make it into the v6? |
Hey, haven't taken a look at this. If you want to give it a try feel free. If we are going to go with something that for now doesn't change the existing API surface as much as possible, then maybe the usage would be something like: public class NewUserViewMail : Mailable<UserModel>
{
private UserModel _user;
private MemoryStream _image;
public NewUserViewMail(UserModel user, MemoryStream image)
{
this._user = user;
this._image = image;
}
public override void Build()
{
this.To(this._user)
.From("from@test.com")
.AddLinkedResource(_image, "image_id") // Signature is `AddLinkedResource(Stream, string)`
.View("~/Views/Mail/NewUser.cshtml", this._user);
}
} So we would have two variations of the method: AddLinkedResource(string filePath, string contentId);
AddLinkedResource(Stream fileStream, string contentId); With this approach, the html will already have set static contentIds for each image, which are then also set using Internally, the If that makes sense, feel free to add one or both of those signatures. Any other ideas welcome too 👍 |
We, actually already have it working great. We took your existing SmtpMailer and created our own with the modification. We could not change the Attachment object to include the needed But, this could be done much simpler by only adding a new private static void SetMailBody(string message, IEnumerable<Attachment> attachments, MimeMessage mail)
{
var bodyBuilder = new BodyBuilder { HtmlBody = message };
if (attachments != null)
{
foreach (var attachment in attachments)
{
if (string.IsNullOrWhiteSpace(attachment.ContentId) == false)
{
var image = bodyBuilder.LinkedResources.Add(attachment.Name, attachment.Bytes);
// We do this instead of using their value because RFC states the Content-Id value must be in the message id format.
image.ContentId = MimeKit.Utils.MimeUtils.GenerateMessageId();
// Now replace where they applied it in the html template with the updated correct version
bodyBuilder.HtmlBody = bodyBuilder.HtmlBody.Replace($"\"cid:{attachment.ContentId}\"", $"\"cid:{image.ContentId}\"");
}
else
bodyBuilder.Attachments.Add(attachment.Name, attachment.Bytes);
}
}
mail.Body = bodyBuilder.ToMessageBody();
} Let me know if you want a PR for this, and I will make the updates with the overload with the Stream type with it. |
That's a pretty cool approach I think @johnwc 😄 If you can make a PR scoped to this specific change I think that would be awesome👍 |
@jamesmh I just create the PR for this. #413 If you are ok with it, I would like to add another small update. In our deployments, we make sure that all emails going out of development environments are prefixed with public class SmtpMailer : IMailer
{
...
public virtual Task BeforeSend(MimeMessage mail)
{
return Task.CompletedTask;
}
public async Task SendAsync(MessageBody message, string subject, IEnumerable<MailRecipient> to, MailRecipient from, MailRecipient replyTo, IEnumerable<MailRecipient> cc, IEnumerable<MailRecipient> bcc, IEnumerable<Attachment> attachments = null, MailRecipient sender = null)
{
var mail = new MimeMessage();
this.SetFrom(@from, mail);
SetSender(sender, mail);
SetRecipients(to, mail);
SetCc(cc, mail);
SetBcc(bcc, mail);
mail.Subject = subject;
SetMailBody(message, attachments, mail);
if (replyTo != null)
{
SetReplyTo(replyTo, mail);
}
using (var client = new SmtpClient())
{
client.ServerCertificateValidationCallback = this._certCallback;
await client.ConnectAsync(this._host, this._port).ConfigureAwait(false);
if (this.UseSMTPAuthentication())
{
await client.AuthenticateAsync(this._username, this._password);
}
await BeforeSend(mail).ConfigureAwait(false);
await client.SendAsync(mail).ConfigureAwait(false);
await client.DisconnectAsync(true).ConfigureAwait(false);
}
}
...
} |
Describe the solution you'd like
We need to be able to add attachments that are considered
LinkedResources
to the MailMessage object, so the attached/embedded images can be used within the html with their ContentId. I will create a PR for this update.@jamesmh Within this PR, is it ok if I add a new property to the
Attachment
class that allows using a Stream? So that a developer can pass a byte array or a Stream.The text was updated successfully, but these errors were encountered: