17

Currently I have to send emails with MailMessage and SmtpClient but I need to send a picture that is currently in base64 string within the MailAddress body.

I have understood that it is necessary to put it in the Attachment, but I don't know how to put base64 in MailMessage class and then read it in order to visualize image in the body of the email. I don't have url image path.

gvivetapl
  • 445
  • 1
  • 5
  • 15
  • Possible duplicate of [Send inline image in email](http://stackoverflow.com/questions/18358534/send-inline-image-in-email) – teo van kot Sep 09 '16 at 09:00

3 Answers3

22

Completed method to convert a body HTML to an AlternateView

bodyHtml example (you can pass it into the MailMessage code block below)

<p>example</p>
<p><img src=\ "data:image/jpeg;base64,---base64string---"></p>
<p>example</p>
<p><img src=\ "data:image/png;base64,---base64string---"></p>
<p>something</p>

With this method, you can visualize multiple images by many ESPs (gmail, outlook,...)

private static AlternateView ContentToAlternateView(string content)
    {
        var imgCount = 0;
        List<LinkedResource> resourceCollection = new List<LinkedResource>();
        foreach (Match m in Regex.Matches(content, "<img(?<value>.*?)>"))
        {
            imgCount++;
            var imgContent = m.Groups["value"].Value;
            string type = Regex.Match(imgContent, ":(?<type>.*?);base64,").Groups["type"].Value;
            string base64 = Regex.Match(imgContent, "base64,(?<base64>.*?)\"").Groups["base64"].Value;
            if (String.IsNullOrEmpty(type) || String.IsNullOrEmpty(base64))
            {
                //ignore replacement when match normal <img> tag
                continue;
            }
            var replacement = " src=\"cid:" + imgCount + "\"";
            content = content.Replace(imgContent, replacement);
            var tempResource = new LinkedResource(Base64ToImageStream(base64), new ContentType(type))
            {
                ContentId = imgCount.ToString()
            };
            resourceCollection.Add(tempResource);
        }

        AlternateView alternateView = AlternateView.CreateAlternateViewFromString(content, null, MediaTypeNames.Text.Html);
        foreach (var item in resourceCollection)
        {
            alternateView.LinkedResources.Add(item);
        }

        return alternateView;
    }

Convert Base64 to Stream:

public static Stream Base64ToImageStream(string base64String)
    {
        byte[] imageBytes = Convert.FromBase64String(base64String);
        MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
        return ms;
    }

Set up MailMessage :

MailMessage mail = new MailMessage();
mail.IsBodyHtml = true;                   
AlternateView alterView = ContentToAlternateView(bodyHtml);
mail.AlternateViews.Add(alterView);
//more settings
//...
//////////////
SmtpClient smtp = new SmtpClient(Host, Port) { EnableSsl = false };
smtp.Send(mail);
nmDat
  • 749
  • 1
  • 9
  • 18
12

To embed image into your mail message: (Its not same as adding an attachment file to message)

You dont need to convert image to base64 if you are using system.net.mail namespace to send your mail.

var mail = new MailMessage();
var imageToInline = new LinkedResource("Your image full path", MediaTypeNames.Image.Jpeg);
            imageToInline.ContentId = "MyImage";
            alternateView.LinkedResources.Add(imageToInline);
mail.AlternateViews.Add(body);

Update:

This is somewhat hacky way of embedding image to your mailMessage.

Byte[] bitmapData = Convert.FromBase64String(FixBase64ForImage("Your base64 image string"));
System.IO.MemoryStream streamBitmap = new System.IO.MemoryStream(bitmapData);

public static string FixBase64ForImage(string Image)
{
        System.Text.StringBuilder sbText = new System.Text.StringBuilder(Image, Image.Length);
        sbText.Replace("\r\n", string.Empty); sbText.Replace(" ", string.Empty);
        return sbText.ToString();
}


var mail = new MailMessage();
var imageToInline = new LinkedResource(streamBitmap , MediaTypeNames.Image.Jpeg);
imageToInline.ContentId = "MyImage";
alternateView.LinkedResources.Add(imageToInline);
mail.AlternateViews.Add(body);

And your html mail body should have following tag:

 <img alt ="" src ="cid:MyImage"/>
Kamalesh Wankhede
  • 1,475
  • 16
  • 37
2
<body>
     <img src='data:image/jpeg;base64, <!-- base64 data --> />
   </body>

use img tag as above in HTML of mail

or you can attach as below

Attachment attachment = new Attachment(base64String);
attachment.TransferEncoding = TransferEncoding.Base64;
mailmessage.Attachments.Add(attachment);
Akshey Bhat
  • 8,227
  • 1
  • 20
  • 20
  • Yes, but how can I Attach base64 image into MailMessage class? – gvivetapl Sep 09 '16 at 08:53
  • why do you want to attach if you can visualize the image using HTML body of email? – Akshey Bhat Sep 09 '16 at 08:55
  • 7
    I think that encoded inline images is not supported by many email clients – gvivetapl Sep 09 '16 at 08:58
  • I am using same approach, but its not working. My `base64String` length is 19000+, and because of this, its throwing an error at `Attachment attachment = new Attachment(base64String);`. – Arsman Ahmad Jul 03 '17 at 08:43
  • @AksheyBhat `PathTooLongException`: too long file name – shmnff Aug 21 '18 at 01:29
  • @Antosha at what line you are getting the exception? I am not using any paths in my code – Akshey Bhat Aug 21 '18 at 01:47
  • @AksheyBhat solved by using stream Attachment at = new Attachment(stream, new ContentType("application/vnd.ms-excel")). Don't forget to reset stream before passing: stream.Seek(0, SeekOrigin.Begin); – shmnff Aug 21 '18 at 06:23
  • 1
    This code makes no sense, there's no overload of Attachment constructor that takes a base64 string, it expects a path or a stream. `new Attachment(base64String);` – AaronLS Dec 14 '20 at 19:22
  • This is not going to work as many client stopped support for this – Manu Mohan Jan 18 '21 at 11:51