2

So I have tried 2 different approaches to creating an inline image using c#:

  1. Using an AlternateView
  2. Using an inline Attachement

Option 2 is worse in that it does not appear inline on any of my test clients (outlook 2010/2013, Samsung android email client, ios 10 email client).

Option 1 is almost perfect, all clients display the inline image correctly as long as there are no other attachments. However, if you add a file attachment to the email, only on the iOS email app you get a strange side effect. On iOS, the client displays both the inline image and the attachment as attachments (the inline image is shown as an icon).

I have tried to figure this out by composing an email in Outlook with an embedded image and an attachment. Outlook generates what looks to be two regular attachments (looking at the raw message data from both Outlook and dotNet generated emails), with the image being marked as content-disposition inline. And this works on all my test clients. Except when using the .Net Mail message api to replicate this (option 2), it doesn't work. I am at a loss to understand what is going on here.

Edit 1

What's interesting is that when using Option 2, the email body is delivered encoded as base64. This is different than how the Outlook client manages to do it. There the body is in plain text and the inline attachment image is the only thing encoded in bas64.

Edit 2 Setting the following properties when using Option 2 returns the body to being plain text again:

mail.BodyEncoding = Encoding.UTF8;
mail.BodyTransferEncoding = TransferEncoding.QuotedPrintable;
Community
  • 1
  • 1
Bitfiddler
  • 3,942
  • 7
  • 36
  • 51

3 Answers3

1

So to get this to work I had to combine both approaches. Below is what worked for me, it displays the signature image as intended (inline/embedded) image and the attachment as an icon (in iOS anyway). This also displayed correctly on a Samsung Android phone and in outlook 2010/2013. For the sake of simplicity, I will only include the embedded image in the mail body as an example:

var smtpMail = new SmtpClient
using (var mail = new MailMessage())
{
    mail.From = new MailAddress(Settings.Default.FromAddress, Settings.Default.FromDisplayName);
    mail.To.Add(toAddress);
    mail.Subject = subjectText;
    mail.IsBodyHtml = true;
    mail.BodyEncoding = Encoding.UTF8;
    mail.BodyTransferEncoding = TransferEncoding.QuotedPrintable;
    mail.Attachments.Add(new Attachment(nonInlinefilePath));

    var imgCid = "img001.jpg"
    var bodyText = $"<html><body><img  src=\"cid:{imgCid}\" alt=\"Sample Image\" /></body></html>";
    var altView = AlternateView.CreateAlternateViewFromString(bodyText, Encoding.UTF8, MediaTypeNames.Text.Html);

    var inlineFileResource = new LinkedResource(imagePath, MediaTypeNames.Image.Jpeg)
    {
        TransferEncoding = TransferEncoding.Base64,
        ContentId = imgCid,
        ContentType =
        {
            Name = imgCid
        },
    };

    var inlineFileAttachment = new Attachment(imagePath, MediaTypeNames.Image.Jpeg)
    {
        ContentId = imgCid
    };
    inlineFileAttachment.ContentDisposition.Inline = true;
    inlineFileAttachment.ContentDisposition.DispositionType = DispositionTypeNames.Inline;

    altView.LinkedResources.Add(inlineFileResource);
    mail.AlternateViews.Add(altView);
    mail.Attachments.Add(inlineFileAttachment);
    smtpMail.Send(mail);
}

I don't know enough about either email protocols or the iOS email app to know why this is necessary, but after many, many, many different attempts to get iOS mail app to display this properly, this combo was the only one that worked.

Bitfiddler
  • 3,942
  • 7
  • 36
  • 51
0

I had a similar issue with a work project. Images embedded in the message body using System.Net.Mail LinkedResource, would appear fine in most email clients, but not with iOS emails after a version upgrade during version 10. The images would have zero bytes and added attachments with zero size. What I did was to fix this was to define the media type, whereas before I didn't.
Before:

    LinkedResource logo = new LinkedResource(HttpContext.Current.Server.MapPath("/images/imgname.png"));

After:

    LinkedResource(HttpContext.Current.Server.MapPath("/images/imgname.png"), "image/png");
chri3g91
  • 1,196
  • 14
  • 16
0

as a possible alternative you could try base64 encoding your image.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAADSCAMAAABThmYtAAAAXVB" alt="img" />

I just tested my image in Outlook, outlook for web, and iOS Mail. worked in all for me.

you could use this tool (or any base64 encoder) to generate a base64 image tag

more info here.

another good source of info on this subject

Sonic Soul
  • 23,855
  • 37
  • 130
  • 196