I'm trying to embed an image in an email that's send with Sendgrid C# 9.28.1. But somehow the image is not displayed. There is also not a function anymore that's called EmbedImage. Is there a way to do this?
var client = new SendGridClient(_settings.ApiKey);
var myMessage = new SendGridMessage();
myMessage.AddTo(entity.Email);
myMessage.From = new EmailAddress(_settings.FromAddress, _settings.FromName);
myMessage.Subject = $"{_settings.FromName} - Image TEST";
var body = "<div style=\"width:200px;\"><img src=\"cid::IMAGE01\"/></div>" +
#"<p>Test message?</p>";
var attachment = new SendGrid.Helpers.Mail.Attachment
{
ContentId = "IMAGE01",
Content = entity.Base64ImageString,
Type = "image/png",
Filename = "image.png"
};
myMessage.AddAttachment(attachment);
myMessage.HtmlContent = body;
await client.SendEmailAsync(myMessage);
I was able to replicate your issue. When running your code I see the image attached, but not inlined into the body of the email.
To resolve the issue, I added the Disposition property and set it to "inline".
message.AddAttachment(new Attachment
{
ContentId = "IMAGE01",
Content = Convert.ToBase64String(File.ReadAllBytes("image.png")),
Type = "image/png",
Filename = "image.png",
Disposition = "inline" // important!
});
Once I added the property, the image was displayed inline. (I also use a single : instead of two : in the HTML, so cid: instead of cid:: but not sure it matters.
Here's what part of my email source looked like without the Disposition property:
<html>
<body>
<img src=3D"cid:IMAGE01"/>
</body>
</html>
--d0e309773e8692891fcbf3a6dc18894582dea28d62adfe2bd8fd84a96b90
Content-Disposition: attachment; filename="image.png"
Content-Transfer-Encoding: base64
Content-Type: image/png; name="image.png"
Notice how IMAGE01 only appears in the HTML, but not in the attachment.
This is with the Disposition property:
<html>
<body>
<img src=3D"cid:IMAGE01"/>
</body>
</html>
--5bb4b7a345af921dc9094ee0d66495c2a390a8aa6e89c2a41d96f8af8af5
Content-Disposition: inline; filename="image.png"
Content-ID: <IMAGE01>
Content-Transfer-Encoding: base64
Content-Type: image/png; name="image.png"
Notice how there's now a Content-ID: <IMAGE01> parameter.
Having said that, there are also two alternatives, you can use a data URL to embed the base64 data into the HTML, or you can upload the image to the internet and reference it.
You can find the source code here: https://github.com/Swimburger/SendGridImages/blob/main/Program.cs
Related
I try to mirror images on my own image hoster, which contains a simple API that accepts default form data uploads like this:
-----------------------------149841124823007
Content-Disposition: form-data; name="file"; filename="ZMVdEwM.png"
Content-Type: image/png
<Binary image data...>
This upload was tested using a simple html form and works well. Now I want to use this API in an .NET Core Standard application. Found different examples:
string url = "https://i.imgur.com/0acC9nr.png";
var client = new HttpClient();
var imageData = client.GetByteArrayAsync(url).Result;
var content = new MultipartFormDataContent($"-----------------------------{DateTime.Now.Ticks}");
content.Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");
string fileName = new Uri(url).LocalPath.Replace("/", "");
content.Add(new ByteArrayContent(imageData), "file", fileName);
var postResp = client.PostAsync("https://my-image-hoster/api.php", content).Result;
string resp = postResp.Content.ReadAsStringAsync().Result;
Console.WriteLine(resp);
I'm downloading the test image https://i.imgur.com/0acC9nr.png as byte array and try to build the same form-data upload. But it fails here on my api:
if (!isset($_FILES['file'])) {
echo json_encode(array('errorcode' => 'no_image_transfered'));
}
While investigation the problem, I inspected the MultipartFormDataContent instance called content since it's responsible for building the request body. It shows a ContentDisposition property containing the file name twice: The first one is correct, but the second one looks maleformed:
What's wrong with my POST request?
Found out that MultipartFormDataContent.Headers.ContentType is the value of the HTTP header:
Content-Type: multipart/form-data; boundary=--------------149841124823007
This was taken from the example, which breaks my API since it expects multipart/form-data. So it's better to dismiss the type, unless your API checks the provided file type in $_FILES['file'][0]['type'] because this is empty. The type came from the body:
Content-Disposition: form-data; name="file"; filename="ZMVdEwM.png"
Content-Type: image/png <--- type
Since it's a value provided by the client, we shouldn't trust this data and fetch the mime-type on the server side. If you have an API that checks this value (and no influence on the API itself) just set it for the body like this:
content.ElementAt(0).Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");
Otherwise if you're fine with a multipart/form-data upload that doesn't contain the mime type, do your upload like this:
string url = "https://i.imgur.com/0acC9nr.png";
var client = new HttpClient();
var imageData = client.GetByteArrayAsync(url).Result;
var content = new MultipartFormDataContent();
string fileName = new Uri(url).LocalPath.Replace("/", "");
content.Add(new ByteArrayContent(imageData), "file", fileName);
// Optionally when the Content-Type body field is required
// content.ElementAt(0).Headers.ContentType = MediaTypeHeaderValue.Parse("image/png");
var postResp = client.PostAsync("https://my-image-hoster/api.php", content).Result;
var resp = postResp.Content.ReadAsStringAsync().Result;
I found this solution for showing an image in the body of the email:
Add image to body of an email
And it works fine but it also adds the image as an attachment to the email.
Attachment inlineLogo = new Attachment(EmailLogo.ImageUrl);
mailMsg.Attachments.Add(inlineLogo);
string contentID = "Image";
inlineLogo.ContentId = contentID;
//To make the image display as inline and not as attachment
inlineLogo.ContentDisposition.Inline = true;
inlineLogo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
//To embed image in email
mailMsg.Body = "<htm><body> <img height=\"49\" width=\"169\" src=\"cid:" + contentID + "\"> </body></html>";
There is a line of code with the comment to display as inline and not as attachment but this line isn't working because the image still gets attached to the email:
//To make the image display as inline and not as attachment
inlineLogo.ContentDisposition.Inline = true;
inlineLogo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
How can I stop the image from attaching to the email?
Use AlternateView to store your html code with image embedded as LinkedResource:
string contentID = "Image";
var inlineLogo = new LinkedResource(EmailLogo.ImageUrl, "image/png");
inlineLogo.ContentId = contentID;
var htmlView = AlternateView.CreateAlternateViewFromString(
"<html><body> <img height=\"30\" width=\"30\" src=\"cid:" + contentID + "\"> </body></html>",
Encoding.UTF8, "text/html");
htmlView.TransferEncoding = TransferEncoding.QuotedPrintable;
htmlView.LinkedResources.Add(inlineLogo);
mailMsg.AlternateViews.Add(htmlView);
P.S. Embedding image as base24 string is not very good idea, because many mail clients do not support such ability.
If you want to display an image in an email it has to exist somewhere. It is either attached as part of the message payload (regardless of whether it is "displayed inline" or as a true "attachment") - or is fetched from a remote web server when the reader reads the email (and optionally has to choose to "view images")
To not attach the image to the email payload itself:
You have to host the image on a public web server so that the reader opening the message can access it.
You have to use a fully qualified URL in your message body source, so it can find it.
Assuming you have stored the image on your web server at the following URL:
http://www.example.com/images/myimage.jpg
... then your source should simply change to reflect:
mailMsg.Body = "<html><body> <img height=\"49\" width=\"169\" src=\"http://www.example.com/images/myimage.jpg\"> </body></html>";
No need to attach it at all.
An alternative that can be used which embeds the image inline, but also isnt generally filtered by email clients is (which is generally the case today in things like junk mail) You could use a DataURL.
<img src="data:image/<type>;base64,<string>"/>
where <type> is the image type, ie jpg, gif,png, and is a base64 string. Just convert the image to a base64 string and assign it to the source using the above syntax
For example, with a jpeg...
mailMsg.Body = "<html><body> <img height=\"49\" width=\"169\" src=\"data:image/jpg;base64,<myPictureString>"\"> </body></html>";
I am trying to send an email with embedded image(Not as attachment file). I am able to send mail.
I'm sending mail using following code:
internal static void Send(SmtpServerConfigurations configurations, EmailMessage emailMsg)
{
using (var mail = InitializeMailMessage(emailMsg))
using (var smtpClient = CreateSmtpClient(configurations))
smtpClient.Send(mail);
}
private static MailMessage InitializeMailMessage(EmailMessage emailMsg)
{
var mail = new MailMessage
{
From = new MailAddress(emailMsg.From),
Subject = emailMsg.Subject,
IsBodyHtml = emailMsg.IsBodyHtml
};
mail.To.Add(emailMsg.To);
AddMessageBody(emailMsg, mail);
return mail;
}
private static void AddMessageBody(EmailMessage emailMsg, MailMessage mail)
{
if (emailMsg.IsBodyHtml)
{
var body = GetHtmlBody(emailMsg.Body, emailMsg.EmbeddedImages);
mail.AlternateViews.Add(body);
}
else
mail.Body = emailMsg.Body;
}
private static AlternateView GetHtmlBody(string body, List<EmbeddedImage> embeddedImages)
{
var alternateView = AlternateView.CreateAlternateViewFromString(body, null,
MediaTypeNames.Text.Html);
if (embeddedImages == null) return alternateView;
foreach (var image in embeddedImages)
{
var imageToInline = new LinkedResource(image.Path, MediaTypeNames.Image.Jpeg);
imageToInline.ContentId = image.Id;
alternateView.LinkedResources.Add(imageToInline);
}
return alternateView;
}
private static SmtpClient CreateSmtpClient(SmtpServerConfigurations config)
{
var smtpClient = new SmtpClient(config.Host);
smtpClient.Port = config.PortNo;
if (config.IsAuthenticationRequired)
smtpClient.Credentials =
new NetworkCredential(config.Username, config.Password);
else
smtpClient.UseDefaultCredentials = true;
smtpClient.EnableSsl = false;
return smtpClient;
}
But the mail sent using above code is not in the format as I want.
What I want is;
MIME-Version: 1.0
From: x#y.com
To: a#b.com
Date: 11 Nov 2016 11:37:52 +0530
Subject: This is subject
Content-Type: multipart/related;
boundary=--boundary_3_1bb3db0a-d33f-46a7-a6ce-60249096160d; type="text/html"
----boundary_3_1bb3db0a-d33f-46a7-a6ce-60249096160d
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN" "=
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xm=
lns =3D "http://www.w3.org/1999/xhtml" > <head ><meta http - equi=
v =3D "content-type" content =3D "text/html; charset=3DUTF-8" /><=
/head ><body style =3D"font-family: Segoe UI; text-align:left;" >=
This is body<br /><img alt =3D"" src =3D"cid:05393c56-15c1-4652-a=
31f-9cc513726bc0" height=3D"50" width=3D"50"/></body ></html >
----boundary_3_1bb3db0a-d33f-46a7-a6ce-60249096160d
Content-Type: image/jpeg name="filename.jpg" <<-----This is what I want.
Content-Transfer-Encoding: base64
Content-ID: <05393c56-15c1-4652-a31f-9cc513726bc0>
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMF
BwYHBwcGBwcI
.
.
.
/w20K7sPt8ul2st3/z0dd36Hj9K9I+HHwj8M6/rLaldaJp8l6y
kGRYgn6LgfpXve0pundwQmk9z//Z
----boundary_3_1bb3db0a-d33f-46a7-a6ce-60249096160d--
What I am getting is;
MIME-Version: 1.0
From: x#y.com
To: a#b.com
Date: 11 Nov 2016 11:37:52 +0530
Subject: This is subject
Content-Type: multipart/related;
boundary=--boundary_3_1bb3db0a-d33f-46a7-a6ce-60249096160d; type="text/html"
----boundary_3_1bb3db0a-d33f-46a7-a6ce-60249096160d
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN" "=
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xm=
lns =3D "http://www.w3.org/1999/xhtml" > <head ><meta http - equi=
v =3D "content-type" content =3D "text/html; charset=3DUTF-8" /><=
/head ><body style =3D"font-family: Segoe UI; text-align:left;" >=
This is body<br /><img alt =3D"" src =3D"cid:05393c56-15c1-4652-a=
31f-9cc513726bc0" height=3D"50" width=3D"50"/></body ></html >
----boundary_3_1bb3db0a-d33f-46a7-a6ce-60249096160d
Content-Type: image/jpeg
Content-Transfer-Encoding: base64
Content-ID: <05393c56-15c1-4652-a31f-9cc513726bc0>
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMF
BwYHBwcGBwcI
.
.
.
/w20K7sPt8ul2st3/z0dd36Hj9K9I+HHwj8M6/rLaldaJp8l6y
kGRYgn6LgfpXve0pundwQmk9z//Z
----boundary_3_1bb3db0a-d33f-46a7-a6ce-60249096160d--
How can I achieve that custom "Name" header in Embedded image section of raw mail?
I want to add that header is because;
When I click on download button shown on image in Gmail inbox, I get "noname" file without extension. That downloaded file isn't useful unless user changes its extension to '.jpg/.jpeg'.
When I tried the same with another component(Which I don't have code for) strangely I was able to download that image with correct filename. Only difference between these two mails was "Name" header.
Please suggest me how to do this or any other way to achieve it.
This will do the trick for you
imageToInline.ContentType.Name = "ImageName.jpg";
I want to send email using System.Web.Mail.MailMessage along with System.Web.Mail.SmtpMail class.
I know that this is a deprecated class but using System.Net.Mail is not an option for me.
So far I am able to send html formatted mail but I am not able to embed image to my email while sending.
This is what I've tried so far;
private static void SendMailMethod(string mailServer, int mailServerPort, string userName, string password)
{
const string SMTP_SERVER = "http://schemas.microsoft.com/cdo/configuration/smtpserver";
const string SMTP_SERVER_PORT =
"http://schemas.microsoft.com/cdo/configuration/smtpserverport";
const string SEND_USING = "http://schemas.microsoft.com/cdo/configuration/sendusing";
const string SMTP_USE_SSL = "http://schemas.microsoft.com/cdo/configuration/smtpusessl";
const string SMTP_AUTHENTICATE =
"http://schemas.microsoft.com/cdo/configuration/smtpauthenticate";
const string SEND_USERNAME =
"http://schemas.microsoft.com/cdo/configuration/sendusername";
const string SEND_PASSWORD =
"http://schemas.microsoft.com/cdo/configuration/sendpassword";
var mailMessage = new System.Web.Mail.MailMessage();
mailMessage.Fields[SMTP_SERVER] = mailServer;
mailMessage.Fields[SMTP_SERVER_PORT] = mailServerPort;
mailMessage.Fields[SEND_USING] = 2;
mailMessage.Fields[SMTP_USE_SSL] = false;
mailMessage.Fields[SMTP_AUTHENTICATE] = 0;
mailMessage.Fields[SEND_USERNAME] = userName;
mailMessage.Fields[SEND_PASSWORD] = password;
mailMessage.From = "abc#xyz.com";
mailMessage.To = "abc#xyz.com";
mailMessage.Subject = "Test mail:";
mailMessage.BodyFormat = MailFormat.Html;
var mailAttachment = new MailAttachment("E:\\imageToEmbed.jpg");
mailMessage.Attachments.Add(mailAttachment);
mailMessage.Attachments.Add(new MailAttachment("E:\\TestAttachmentFile.txt"));
var htmlBody =
"<!DOCTYPE html PUBLIC \" -//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" +
"<html xmlns = \"http://www.w3.org/1999/xhtml\" >" +
" <head >" +
"<meta http - equiv = \"content-type\" content = \"text/html; charset=UTF-8\" />" +
"</head >" +
"<body style = \"font-family: Segoe UI; text-align:left;\" >" +
"Following is an embedded image:" +
"<br />" +
"<img alt = \"\" src = \"imageToEmbed.jpg\" />" +
"</body >" +
"</html >";
mailMessage.Body = htmlBody;
try
{
SmtpMail.Send(mailMessage);
Console.WriteLine("Mail sent");
}
catch (Exception ex)
{
Console.WriteLine("Error:" + ex.ToString());
throw ex;
}
}
This code sends email but instead of showing image, the mail shows small square with a cross in it.
How can I embed this "imageToEmbed.jpg" to my email.
You can't achieve that with the classes System.Web.Mail because that implementation abstracts the access to a lot of features of the underlying Collaboration Data Objects component.
Instead of using the wrapper offered by System.Web.Mail.Message you better switch to using the CDO COM object directly. Add a reference to Microsoft CDO for Windows 2000 Library from the COM tab in the reference dialog.
After that you can use the following code to create and send an html email with embedded images:
var cdo = new CDO.Message();
// configuration
var cfg = cdo.Configuration;
cfg.Fields[SMTP_SERVER].Value = "smtp.server.com";
cfg.Fields[SMTP_SERVER_PORT].Value = 22;
cfg.Fields[SEND_USING].Value = 2;
cfg.Fields[SMTP_USE_SSL].Value = true;
cfg.Fields[SMTP_AUTHENTICATE].Value = 1;
cfg.Fields[SEND_USERNAME].Value = "user#example.com";
cfg.Fields[SEND_PASSWORD].Value = "password";
cfg.Fields.Update();
cdo.To = "awesome#example.com";
cdo.Sender = "me#example.com";
// attachment
var cdoatt = cdo.AddAttachment("file:///E:/imageToEmbed.jpg");
//this is why System.Web.Mail can't embed images
cdoatt.Fields["urn:schemas:mailheader:content-id"].Value = Guid.NewGuid().ToString("N");
cdoatt.Fields.Update();
// get a reference to out content-id field
var cid = cdoatt.Fields["urn:schemas:mailheader:content-id"];
// notice the special layout of SRC on the image tag,
//it will be somethong like CID:123456789abcdef
cdo.HTMLBody = #"<HTML><BODY><B>CDO</B><BR /> <IMG SRC=""cid:" + cid.Value + #"""/></BODY></HTML>";
cdo.Send();
Notice how you can set the Content-ID header here on the Attachment. That is needed so you can use the Content-ID in the SRC attribute of your image.
A typical mailmessage will look
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_NextPart_000_0001_01D1AF72.C8AE8C70"
Content-Transfer-Encoding: 7bit
X-Mailer: Microsoft CDO for Windows 2000
Content-Class: urn:content-classes:message
Importance: normal
Priority: normal
X-MimeOLE: Produced By Microsoft MimeOLE V10.0.10011.16384
This is a multi-part message in MIME format.
------=_NextPart_000_0001_01D1AF72.C8AE8C70
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_0002_01D1AF72.C8AE8C70"
------=_NextPart_001_0002_01D1AF72.C8AE8C70
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
plain cdo
------=_NextPart_001_0002_01D1AF72.C8AE8C70
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
<HTML><BODY><B>plain cdo</B> <IMG SRC="cid:42"/></BODY></HTML>
------=_NextPart_001_0002_01D1AF72.C8AE8C70--
------=_NextPart_000_0001_01D1AF72.C8AE8C70
Content-Type: image/png;
name="file.png"
Content-Transfer-Encoding: base64
Content-ID: <42>
Content-Disposition: attachment;
filename="file.png"
iVBORw0KGgoAAAANSUhEUgAAADQAAABLCAMA
Notice the Content-ID (here 42).
When using the plain System.Web.Mail classes your raw email will look like this:
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_NextPart_000_0000_01D1AF70.59FC25F0"
X-Mailer: Microsoft CDO for Windows 2000
Content-Class: urn:content-classes:message
Importance: normal
Priority: normal
X-MimeOLE: Produced By Microsoft MimeOLE V10.0.10011.16384
This is a multi-part message in MIME format.
------=_NextPart_000_0000_01D1AF70.59FC25F0
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_0001_01D1AF70.59FC25F0"
------=_NextPart_001_0001_01D1AF70.59FC25F0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Following is an embedded image:
_____
test afterit
------=_NextPart_001_0001_01D1AF70.59FC25F0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
<!DOCTYPE html PUBLIC " -//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns = "http://www.w3.org/1999/xhtml" > <head ><meta http - equiv = "content-type" content = "text/html; charset=UTF-8" /></head ><body style = "font-family: Segoe UI; text-align:left;" ><i>Following is an embedded image:</i><br /><img alt = "" src ="<file:///file.png>"/><hr><b>test afterit</b></body ></html >
------=_NextPart_001_0001_01D1AF70.59FC25F0--
------=_NextPart_000_0000_01D1AF70.59FC25F0
Content-Type: image/png;
name="file.png"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="file.png"
iVBORw0KGgoAAAANSUhEUgAAADQAAABLCAMAAAAI0l
As you can see, there is no Content-ID header added and there is no code-path from the .Net implementation to add that header.
It might not find the image in the specified path or it might be a permission thing hence the broken image thingy. You need to check that first but if you would use base64 you will have the image in a string.
Try changing the image to a base64 link to a free online converter page.
This link might help as well c# embed base64 image for emailing.
I am using EWS to receive/send emails. I am sending embedded images in the email to navigate users to another page. However, when sending to other emails clients like gmail and yahoo, the images are not being set as html, but text. I created a console app below to demonstrate:
static void Main(string[] args)
{
var service = getExchangeService(NetworkCreds.Credentials);
// Create the HTML body with the content identifier of the attachment.
string html = #"<html>
<head>
</head>
<body>
<img width=100 height=100 id=""1"" src=""cid:Party.jpg"">
</body>
</html>";
// Create the email message.
EmailMessage email = new EmailMessage(service);
email.Subject = "Test Email";
email.Body = new MessageBody(BodyType.HTML, html);
email.ToRecipients.Add("test#gmail.com");
// Add the attachment to the local copy of the email message.
string file = #"C:\projects\Party.jpg";
email.Attachments.AddFileAttachment("Party.jpg", file);
email.Attachments[0].IsInline = true;
email.Attachments[0].ContentId = "Party.jpg";
// Save a copy of the email, add the attachment, and then send the email. This method results in three calls to EWS.
email.SendAndSaveCopy();
}
When I receive the message in outlook it works fine but in gmail it only has the following text in the body: [cid:Party.jpg] with the file attachment below. I know Gmail and other clients have extensive processing of images and that may the case of why it's not displaying correctly. My question is if inline images can be sent from exchange web services to other clients and be processed correctly?
This is how you fix this kind of thing
bodyText = bodyText.Replace("cid:" + fileAttachment.ContentId, fileAttachment.Name);
Be sure to attach the file as "Image 001.png" or whatever it is, then you can resend this e-mail with images in tact :)
I know that i am a bit late but maybe someone else will stuck at a similar problem and this could help solving the problem.
You could set the image as base64 encoded image.
In my case i wanted to load a preview of an existing email in a browser control.
Everything worked except showing the images. But replacing them to base64 encoded strings worked perfectly.
In this example following code should work as described:
EmailMessage email = new EmailMessage(service);
email.Subject = "Test Email";
email.Body = new MessageBody(BodyType.HTML, html);
email.ToRecipients.Add("test#gmail.com");
// Add the attachment to the local copy of the email message.
string file = #"C:\projects\Party.jpg";
MemoryStream stream = new MemoryStream();
email.Attachments.AddFileAttachment("Party.jpg", file).Load(stream);
byte[] imageBytes = stream.ToArray();
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(imageBytes);
stream.close();
email.Attachments[0].IsInline = true;
email.Attachments[0].ContentId = "Party.jpg";
string html = #"<html>
<head>
</head>
<body>
<img width=100 height=100 id=""1"" src=""data: image/jpg;base64, " + base64String + """>
</body>
</html>";