Issue with Gmail - Embedded images using MailKit - c#

I'm trying to send emails with embedded images using MailKit. It works well on MS Outlook. However, images do not display as embedded images in Gmail. I tried to attach with "data:image/png;base64," format to it also worked on Outlook but not Gmail.
Any help would be much appreciated!
public string SendEmail (MyModel myModel)
{
var message = new MimeMessage();
var bodyBuilder = new BodyBuilder
{
HtmlBody = myModel.Body
};
GetAllImgTags(bodyBuilder);
message.Body = bodyBuilder.ToMessageBody();
// Send Email Here...
return "OK"
}
public string GetAllImgTags(BodyBuilder bodyBuilder)
{
HtmlDocument document = new HtmlDocument();
document.LoadHtml(bodyBuilder.HtmlBody);
var imgList = document.DocumentNode.Descendants("img").Where(x =>
{
string src = x.GetAttributeValue("src", null) ?? "";
return !string.IsNullOrEmpty(src);
}).ToList();
foreach(var item in imgList)
{
string currentSrcValue = item.GetAttributeValue("src", null);
var file = Path.Combine(_env.WebRootPath,"images", currentSrcValue);
if (File.Exists(file))
{
byte[] imageData = System.IO.File.ReadAllBytes(file);
string contentId = string.Format("{0}#{1}", Path.GetFileName(file), Guid.NewGuid().ToString());
LinkedResource inline = new LinkedResource(new MemoryStream(imageData), Image.Jpeg)
{
ContentId = contentId,
TransferEncoding = TransferEncoding.Base64,
ContentLink = new Uri("cid:" + contentId),
};
inline.ContentType.Name = contentId;
inline.ContentType.MediaType = Image.Jpeg;
bodyBuilder.LinkedResources.Add(contentId, new MemoryStream(imageData));
item.SetAttributeValue("src", "cid:" + contentId);
inline.Dispose();
}
}
bodyBuilder.HtmlBody = document.DocumentNode.OuterHtml;
string result = document.DocumentNode.OuterHtml;
return result;
}

Well, first of all, why are you creating System.Net.Mail objects and then simply disposing them without using them in any way?
See this code for what I mean:
LinkedResource inline = new LinkedResource(new MemoryStream(imageData), Image.Jpeg)
{
ContentId = contentId,
TransferEncoding = TransferEncoding.Base64,
ContentLink = new Uri("cid:" + contentId),
};
inline.ContentType.Name = contentId;
inline.ContentType.MediaType = Image.Jpeg;
Let's try this instead:
var contentType = new ContentType ("image", "jpeg");
var contentId = MimeKit.Utils.MimeUtils.GenerateMessageId ();
var image = (MimePart) bodyBuilder.LinkedResources.Add (file, contentType);
image.ContentTransferEncoding = ContentEncoding.Base64;
image.ContentId = contentId;
item.SetAttributeValue ("src", "cid:" + contentId);

Related

Is it possible to embed images in email without having them listed as attachments?

So far, I have managed to embed images into my e-mail template rendered with RazorEngine. But, I am not quite satisfied with how it looks right now.
As it can be seen, they appear as attachments and quite in ugly way. What are the options to beautify the resulting output? Thanks in advance.
Here is the code responsible for this:
private async Task<MailMessage> PrepareEmailData(AppUser user)
{
var (body, models) = await PrepareHtmlContentWithModels(user);
var emailMessage = new MailMessage
{
From = new MailAddress("someemail#gmail.com", "Bla-bla-bla"),
Subject = "Weekly summary",
IsBodyHtml = true,
Body = body,
Priority = MailPriority.Normal,
};
emailMessage.To.Add(new MailAddress(user.Email));
var alternateView = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
var imageLinks = new List<LinkedResource>();
models.BoardThreadWithRepliesModels.ForEach(e =>
imageLinks.Add(new LinkedResource(e.ThreadMainPicturePath, "image/png")
{
ContentId = e.ThreadMainPictureContentId,
TransferEncoding = TransferEncoding.Base64
}));
models.BoardThreadWithRepliesModels
.ForEach(e =>
e.Replies
.Where(r => !string.IsNullOrWhiteSpace(r.PicRelatedPath))
.ToList()
.ForEach(r =>
{
imageLinks.Add(new LinkedResource(r.PicRelatedPath, "image/png")
{
ContentId = r.PicRelatedContentId,
TransferEncoding = TransferEncoding.Base64
});
}));
imageLinks.ForEach(e => alternateView.LinkedResources.Add(e));
emailMessage.AlternateViews.Add(alternateView);
return emailMessage;
}

Convert Word document attached with note to PDF in CRM

I need your help. I want to convert word document attached with note into PDF and send it to customer. I have retrieved note attachment with invoice entity, but unable to convert it into PDF. Please see below code.
Entity emailCreated = service.Retrieve("email", SourceEmailID, new ColumnSet(true));
QueryExpression QueryNotes = new QueryExpression("annotation");
QueryNotes.ColumnSet = new ColumnSet(new string[] { "subject", "mimetype", "filename", "documentbody" });
QueryNotes.Criteria = new FilterExpression();
QueryNotes.Criteria.FilterOperator = LogicalOperator.And;
QueryNotes.Criteria.AddCondition(new ConditionExpression("objectid", ConditionOperator.Equal, invoiceID.Id));
EntityCollection MimeCollection = service.RetrieveMultiple(QueryNotes);
if (MimeCollection.Entities.Count > 0)
{ //we need to fetch first attachment
Entity NotesAttachment = MimeCollection.Entities.First();
//Create email attachment
Entity EmailAttachment = new Entity("activitymimeattachment");
if (NotesAttachment.Contains("subject"))
EmailAttachment["subject"] = NotesAttachment.GetAttributeValue<string>("subject");
EmailAttachment["objectid"] = new EntityReference("email", emailCreated.Id);
EmailAttachment["objecttypecode"] = "email";
if (NotesAttachment.Contains("filename"))
EmailAttachment["filename"] = NotesAttachment.GetAttributeValue<string>("filename");
if (NotesAttachment.Contains("documentbody"))
EmailAttachment["body"] = NotesAttachment.GetAttributeValue<string>("documentbody");
if (NotesAttachment.Contains("mimetype"))
EmailAttachment["mimetype"] = NotesAttachment.GetAttributeValue<string>("mimetype");
service.Create(EmailAttachment);
}
// Sending email
SendEmailRequest SendEmail = new SendEmailRequest();
SendEmail.EmailId = emailCreated.Id;
SendEmail.TrackingToken = "";
SendEmail.IssueSend = true;
SendEmailResponse res = (SendEmailResponse)service.Execute(SendEmail);
I change only few lines as, file name is static in this case but you can change it later.
if (NotesAttachment.Contains("filename"))
EmailAttachment["filename"] = "abc.pdf";
if (NotesAttachment.Contains("documentbody"))
EmailAttachment["body"] = Convert.ToBase64String(NotesAttachment.GetAttributeValue<string>("documentbody"));
if (NotesAttachment.Contains("mimetype"))
EmailAttachment["mimetype"] = "text/plain";
Try below code,
Entity emailCreated = service.Retrieve("email", SourceEmailID, new ColumnSet(true));
QueryExpression QueryNotes = new QueryExpression("annotation");
QueryNotes.ColumnSet = new ColumnSet(new string[] { "subject", "mimetype", "filename", "documentbody" });
QueryNotes.Criteria = new FilterExpression();
QueryNotes.Criteria.FilterOperator = LogicalOperator.And;
QueryNotes.Criteria.AddCondition(new ConditionExpression("objectid", ConditionOperator.Equal, invoiceID.Id));
EntityCollection MimeCollection = service.RetrieveMultiple(QueryNotes);
if (MimeCollection.Entities.Count > 0)
{ //we need to fetch first attachment
Entity NotesAttachment = MimeCollection.Entities.First();
//Create email attachment
Entity EmailAttachment = new Entity("activitymimeattachment");
if (NotesAttachment.Contains("subject"))
EmailAttachment["subject"] = NotesAttachment.GetAttributeValue<string>("subject");
EmailAttachment["objectid"] = new EntityReference("email", emailCreated.Id);
EmailAttachment["objecttypecode"] = "email";
if (NotesAttachment.Contains("filename"))
EmailAttachment["filename"] = "abc.pdf";
if (NotesAttachment.Contains("documentbody"))
EmailAttachment["body"] = Convert.ToBase64String(NotesAttachment.GetAttributeValue<string>("documentbody"));
if (NotesAttachment.Contains("mimetype"))
EmailAttachment["mimetype"] = "text/plain";
service.Create(EmailAttachment);
}
// Sending email
SendEmailRequest SendEmail = new SendEmailRequest();
SendEmail.EmailId = emailCreated.Id;
SendEmail.TrackingToken = "";
SendEmail.IssueSend = true;
SendEmailResponse res = (SendEmailResponse)service.Execute(SendEmail);

app crashes before the request is sent to the server

I'm building an android app with Xamarin which communicates with an ASP.net server's API. I'm trying to upload a file to the server using the following lines of code:
public async Task<HttpResponseMessage> UploadFile(byte[] file)
{
var progress = new System.Net.Http.Handlers.ProgressMessageHandler();
//progress.HttpSendProgress += progress_HttpSendProgress;
using (var client = HttpClientFactory.Create(progress))
{
client.BaseAddress = new Uri(GlobalVariables.host);
// Set the Accept header for BSON.
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/bson"));
var request = new uploadFileModel { data = file, dateCreated = DateTime.Now, fileName = "myvideooo.mp4", username = "psyoptica" };
// POST using the BSON formatter.
MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
var m = client.MaxResponseContentBufferSize;
var result = await client.PostAsync("api/media/upload", request, bsonFormatter);
return result.EnsureSuccessStatusCode();
}
}
The app crashes before the server receives the request. The file I'm trying to upload could be a video or an audio file. The server receives the request after the app has crashed. This works fine on the local server but the crash happens with the live server. My server side code looks like this:
[HttpPost]
[Route("upload")]
public async Task<HttpResponseMessage> Upload(uploadFileModel model)
{
var result = new HttpResponseMessage(HttpStatusCode.OK);
if (ModelState.IsValid)
{
string thumbname = "";
string resizedthumbname = Guid.NewGuid() + "_yt.jpg";
string FfmpegPath = Encoding_Settings.FFMPEGPATH;
string tempFilePath = Path.Combine(HttpContext.Current.Server.MapPath("~/tempuploads"), model.fileName);
string pathToFiles = HttpContext.Current.Server.MapPath("~/tempuploads");
string pathToThumbs = HttpContext.Current.Server.MapPath("~/contents/member/" + model.username + "/thumbs");
string finalPath = HttpContext.Current.Server.MapPath("~/contents/member/" + model.username + "/flv");
string resizedthumb = Path.Combine(pathToThumbs, resizedthumbname);
var outputPathVid = new MediaFile { Filename = Path.Combine(finalPath, model.fileName) };
var inputPathVid = new MediaFile { Filename = Path.Combine(pathToFiles, model.fileName) };
int maxWidth = 380;
int maxHeight = 360;
var namewithoutext = Path.GetFileNameWithoutExtension(Path.Combine(pathToFiles, model.fileName));
thumbname = model.VideoThumbName;
string oldthumbpath = Path.Combine(pathToThumbs, thumbname);
var fileName = model.fileName;
File.WriteAllBytes(tempFilePath, model.data);
if (model.fileName.Contains("audio"))
{
File.WriteAllBytes(Path.Combine(finalPath, model.fileName), model.data);
string audio_thumb = "mic_thumb.jpg";
string destination = Path.Combine(pathToThumbs, audio_thumb);
string source = Path.Combine(pathToFiles, audio_thumb);
if (!System.IO.File.Exists(destination))
{
System.IO.File.Copy(source, destination, true);
}
Video_Struct vd = new Video_Struct();
vd.CategoryID = 0; // store categoryname or term instead of category id
vd.Categories = "";
vd.UserName = model.username;
vd.Title = "";
vd.Description = "";
vd.Tags = "";
vd.OriginalVideoFileName = model.fileName;
vd.VideoFileName = model.fileName;
vd.ThumbFileName = "mic_thumb.jpg";
vd.isPrivate = 0;
vd.AuthKey = "";
vd.isEnabled = 1;
vd.Response_VideoID = 0; // video responses
vd.isResponse = 0;
vd.isPublished = 1;
vd.isReviewed = 1;
vd.Thumb_Url = "none";
//vd.FLV_Url = flv_url;
vd.Embed_Script = "";
vd.isExternal = 0; // website own video, 1: embed video
vd.Type = 0;
vd.YoutubeID = "";
vd.isTagsreViewed = 1;
vd.Mode = 0; // filter videos based on website sections
long videoid = VideoBLL.Process_Info(vd, false);
}
else
{
using (var engine = new Engine())
{
engine.GetMetadata(inputPathVid);
// Saves the frame located on the 15th second of the video.
var outputPathThumb = new MediaFile { Filename = Path.Combine(pathToThumbs, thumbname+".jpg") };
var options = new ConversionOptions { Seek = TimeSpan.FromSeconds(0), CustomHeight = 360, CustomWidth = 380 };
engine.GetThumbnail(inputPathVid, outputPathThumb, options);
}
Image image = Image.FromFile(Path.Combine(pathToThumbs, thumbname+".jpg"));
//var ratioX = (double)maxWidth / image.Width;
//var ratioY = (double)maxHeight / image.Height;
//var ratio = Math.Min(ratioX, ratioY);
var newWidth = (int)(maxWidth);
var newHeight = (int)(maxHeight);
var newImage = new Bitmap(newWidth, newHeight);
Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
Bitmap bmp = new Bitmap(newImage);
bmp.Save(Path.Combine(pathToThumbs, thumbname+"_resized.jpg"));
//File.Delete(Path.Combine(pathToThumbs, thumbname));
using (var engine = new Engine())
{
var conversionOptions = new ConversionOptions
{
VideoSize = VideoSize.Hd720,
AudioSampleRate = AudioSampleRate.Hz44100,
VideoAspectRatio = VideoAspectRatio.Default
};
engine.GetMetadata(inputPathVid);
engine.Convert(inputPathVid, outputPathVid, conversionOptions);
}
File.Delete(tempFilePath);
Video_Struct vd = new Video_Struct();
vd.CategoryID = 0; // store categoryname or term instead of category id
vd.Categories = "";
vd.UserName = model.username;
vd.Title = "";
vd.Description = "";
vd.Tags = "";
vd.Duration = inputPathVid.Metadata.Duration.ToString();
vd.Duration_Sec = Convert.ToInt32(inputPathVid.Metadata.Duration.Seconds.ToString());
vd.OriginalVideoFileName = model.fileName;
vd.VideoFileName = model.fileName;
vd.ThumbFileName = thumbname+"_resized.jpg";
vd.isPrivate = 0;
vd.AuthKey = "";
vd.isEnabled = 1;
vd.Response_VideoID = 0; // video responses
vd.isResponse = 0;
vd.isPublished = 1;
vd.isReviewed = 1;
vd.Thumb_Url = "none";
//vd.FLV_Url = flv_url;
vd.Embed_Script = "";
vd.isExternal = 0; // website own video, 1: embed video
vd.Type = 0;
vd.YoutubeID = "";
vd.isTagsreViewed = 1;
vd.Mode = 0; // filter videos based on website sections
//vd.ContentLength = f_contentlength;
vd.GalleryID = 0;
long videoid = VideoBLL.Process_Info(vd, false);
}
return result;
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
}
}`
What am I doing wrong here that's making the app crash. Is there a better way to do this?
Any help is appreciated.

How to get PlainText or Html Text using AE.Net.Mail?

I'm trying to get Plain Text or HTML Text of email using AE.Net.Mail.
I cannot find any documentation.
using (Pop3Client pop3 = new AE.Net.Mail.Pop3Client("pop3Server", "login", "pwd", 995, true))
{
for (var i = pop3.GetMessageCount() - 1; i >= 0; i--)
{
MailMessage Msg = pop3.GetMessage(i);
string HtmlText = Msg.??????
string PlainText = Msg.??????
}
}
Edit : I found this solution
IList<Attachment> iList;
string HtmlText = "", PlainText = "";
for (var i = pop3.GetMessageCount() - 1; i >= 0; i--)
{
MailMessage msg = pop3.GetMessage(i);
TextBody = msg.Body;
iList = msg.AlternateViews as IList<Attachment>;
if (iList.Count == 0) iList = msg.Attachments as IList<Attachment>;
if (iList.Count > 0)
{
TextBody = iList[0].Body;
HtmlBody = iList[1].Body;
}
}
I solved this problem with this method:
Firt create a class:
class BodyContent
{
public string ContentType { get; set; }
public string Body { get; set; }
}
Than:
List<BodyContent> bodies = new List<BodyContent>();
foreach (AE.Net.Mail.Attachment item in mail.AlternateViews)
{
bodies.Add(new BodyContent
{
ContentType = item.ContentType,
Body = item.Body
});
}
And check has "text/html":
string body="";
BodyContent bodyTemp= bodies.Find(x => x.ContentType == "text/html");
if (bodyTemp== null)
body = mail.Body;
else
body = bodyTemp.Body;
And if has "text/html", body's format html else body's format plain
Body = e.Value.AlternateViews.GetHtmlView().Body,
If your MailMessage is the System.Net.Mail one, you can get the message body from the Body property. It may be either HTML or plain-text depending on the IsBodyHtml property. The AlternateViews property may also contain alternate forms of the message body.
you must set headers only to false
foreach (var item in mm)
{
Email myM = new Email();
myM.Date = item.Date;
myM.Body = item.Body;

sending mailchimp campaign in asp.net

I'm trying to send a mail chimp campaign using asp.net, actually i created successfully the campaign and i can see it through my profile but also i want to send it through my code here is my code so if any one can help!!
private static void CreateCampaignAndSend(string apiKey, string listID)
{
Int32 TemplateID = 0;
string campaignID = string.Empty;
// compaign Create Options
var campaignCreateOpt = new campaignCreateOptions
{
list_id = listID,
subject = "subject",
from_email = "cbx#abc.com",
from_name = "abc",
template_id = TemplateID
};
// Content
var content = new Dictionary<string, string>
{
{"html", "Lots of cool stuff here."}
};
// Conditions
var csCondition = new List<campaignSegmentCondition>();
var csC = new campaignSegmentCondition {field = "interests-" + 123, op = "all", value = ""};
csCondition.Add(csC);
// Options
var csOptions = new campaignSegmentOptions {match = "all"};
// Type Options
var typeOptions = new Dictionary<string, string>
{
{"offset-units", "days"},
{"offset-time", "0"},
{"offset-dir", "after"}
};
// Create Campaigns
var campaignCreate = new campaignCreate(new campaignCreateInput(apiKey, EnumValues.campaign_type.plaintext, campaignCreateOpt, content, csOptions, typeOptions));
campaignCreateOutput ccOutput = campaignCreate.Execute();
campaignSendNow c=new campaignSendNow();
List<Api_Error> error = ccOutput.api_ErrorMessages; // Catching API Errors
if (error.Count <= 0)
{
campaignID = ccOutput.result;
}
else
{
foreach (Api_Error ae in error)
{
Console.WriteLine("\n ERROR Creating Campaign : ERRORCODE\t:" + ae.code + "\t ERROR\t:" + ae.error);
}
}
}

Categories