I store emails and their attachments in a database. I'm using a WPF WebBrowser and the NavigateToString method to display the html body of emails. It works but when emails use embedded images with a content id (cid), i can't display them. I saved all embedded images as attachments when i save emails in database. I could create and store images in temporary files of the current user and replace cid references with an absolute path on user's disk but i think it's not the best way...
Have you got some ideas ?
I finally found a good way :
I replaced the cid references of all images with base64 image data (RFC 2557) like this :
<img src="data:image/png;base64,RAAAtuhhx4dbgYKAAA7...more data....." alt="test">
You can use the following code to generate the base64 string :
string base64Str = Convert.ToBase64String(File.ReadAllBytes(#"C:\Temp\test.png"));
Remarks : doesn't work with IE6
Related
I'm writing a WinForms application. I created a Google Doc template file that contains placeholders like {{name}} for various text elements. I can successfully make a copy of this document and use the BatchUpdateDocumentRequest to modify them just fine.
However, I also have an embedded image in the document. I can obtain the objectId for this image just fine. I either want to replace this image with another or remove it from my template and then append my new image to the end of the document. In both cases, the InsertInlineImage or ReplaceImage classes require a URI of the image to insert or replace with. This is where I have an issue.
The image itself has been captured from a control on the WinForms. Its actually a chart. I've saved the image in PNG format since I know that is one of the formats supported by Google drive/docs. I figured in order to use it in the batch update, I would need to upload it first, so I did and got its file id and webcontentlink back in the response.
I'm not locked into any particular way of doing this. I originally tried creating an HTML file, uploading but then it would strip the image from it, so became useless, so I switched gears to using a Google Doc as my template and just try to replace elements in it instead. This went well until I got to the image.
Essentially no matter what I try to specify as the URI, it says the file in not in a supported format.
As far as I can tell, Google expects the URI to actually end in .png or be a real link versus a download URL you'd get from Google Drive.
Here is an example of the code I'm using to attempt to replace the image. The strImageObjectId is the objectId of the Embedded Object image in the template document copy that I want to replace. The Uri is what Google needs to pull the new image from. I'm happy to pull it from my local computer or Google Drive if only I could get it to accept it somehow.
BatchUpdateDocumentRequest batchUpdateRequest = new BatchUpdateDocumentRequest {
Requests = new List<Google.Apis.Docs.v1.Data.Request>()
};
request = new Google.Apis.Docs.v1.Data.Request {
ReplaceImage = new ReplaceImageRequest() {
ImageObjectId = strImageObjectId,
Uri = strChartWebContentLink
}
};
batchUpdateRequest.Requests.Add(request);
DocumentsResource.BatchUpdateRequest updateRequest =
sDocsService.Documents.BatchUpdate(batchUpdateRequest, strCopyFileId);
BatchUpdateDocumentResponse updateResponse = updateRequest.Execute();
I'm happy to use whatever method will get me to a point where I an end up with a Google Doc on Google Drive that was based on a template in which I can replace various text elements, but most importantly add/replace an image.
Thanks so much for the advice.
I got to the point were I believe I was specifying the URI correctly, but then I started getting an access forbidden error instead.
I didn't have time to hunt this one down, so I went back to creating an HTML template with my image, uploading as a Google Doc, exporting to PDF, and then uploading as a PDF. This ended up working because originally I was using a BMP as the file format and that is not supported by Google Docs, so I changed to a PNG instead and it worked just fine.
I think Google Docs needs to add the ability to add an image using a MemoryStream or some other programmatic base64 resource instead of purely being based on URIs and running into temporary upload or permission issues.
Hey I'm doing the same thing with you,
and I got this, by modify the download link format.
from this:
https://docs.google.com/uc?export=download&id={{YOUR GDRIVE IMAGE
ID}
to this
https://docs.google.com/uc?export=view&id={{YOUR GDRIVE IMAGE ID}
e.g :
uri: "https://docs.google.com/uc?export=view&id=1cjgyHqtYSgS0CBT4x-9eQIHRzOIfGgv-"
but the image should be set for public privilege
I have a the following setup to send emails from my c# Application :
SmtpClient (under System.Net.Mail namespace) to do the actual sending once everything is in place and set the 'IsBodyHtml' property of the Message object to True
Using the dll from Sautinsoft I convert a simple rtf file which contains the formatting of the email and convert it to a HTML string which I then use as the body of the mail.
It works great just as it is and I have sent a few test emails to myself and all the appropriate formatting is retained. However i am having a problem with images - The dll converts images to a img tag and uses the base 64 format of the image as the data source, this works fine if you view it as a html page, but sending it as the body of you email produces problems. Email clients such as Yahoo don't mind embedded images but Gmail does not play nice with this methodology. The only image that should appear in the emails I'm sending is the signature image located at the bottom of each email. Using signatures in the native Gmail client in your browser poses no problems since the image has a link to a actual file on a server somewhere, but sending emails with signatures via a C# Application seems to be a different story. Any suggestions?
Thank you for your time.
You may consider automating Outlook from a C# application. See How to automate Outlook and Word by using Visual C# .NET to create a pre-populated e-mail message that can be edited. Also you can find a sample code - C# app automates Outlook (CSAutomateOutlook).
If you are talking about RTF2HTML, you may add any images in a separate folder (no include in body of HTML):
string inpFile = #"..\..\..\..\example.docx";
string outFile = Path.GetFullPath(#"Result2.html");
string imgDir = Path.GetDirectoryName(outFile);
RtfToHtml r = new RtfToHtml();
// Set images directory
HtmlFixedSaveOptions opt = new HtmlFixedSaveOptions()
{
ImagesDirectoryPath = Path.Combine(imgDir, "Result_images"),
ImagesDirectorySrcPath = "Result_images",
// Change to store images as physical files on local drive.
EmbedImages = false
};
try
{
r.Convert(inpFile, outFile, opt);
}
catch (Exception ex)
{
Console.WriteLine($"Conversion failed! {ex.Message}");
}
As the result you will see HTML file with linked images in folder.
I am updating an asp.net application and saving and retrieving documents from a mssql database. Saving was very simple but is there a way to download a file from an anchor that directly downloads from the database? Lets just say that that blob is bound within a gridview or some other data control, I would like to do this, example: Download Doc. I save the file name as well.
First, you wouldn't assign the image to the href element, you would create an img tag to display the image, then the href tag to download it or embed the image tag directly in the href:
<img src="<%#Eval("blobcolumn")%></img>
Second, displaying the image inline without Url to a file requires a Data URI, which means that a base-64 version of the image is embedded in the web page:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">
This approach means a substantial amount of extra traffic on your web server and your end user's machines since the image will not be cached as it would be if you provided an actual URL to the image in your web server (i.e. /images/reddot.png).
I think that you would be much better off saving copies of the image to the web server and providing urls to those images in your page.
If there is concern about the size or number of files, you could create batch jobs to purge files older than a certain number of days or hours from the temporary image cache.
You can create a Handler to download data.
sample.ashx
public void ProcessRequest (HttpContext context)
{
string id = context.Request["id"];
if (!string.IsNullOrEmpty(id))
{
//read byte[] and other data from database based upon given ID
byte []ar=//result from database
string fileName=//filename
context.Response.ContentType = "Application/octet-stream";
context.Response.AddHeader("Content-Length", ar.Length.ToString());
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName );
context.Response.BinaryWrite(ar);
context.Response.Flush();
context.Response.End();
}
}
and request via hyperlinks
Download .zip
<a href='sample.ashx?id=<%#Eval("ID")%>'><%#Eval("Desc")%></a>
I want to know how to create an image object having the "src info from an email". I already manage to get read the inbox, and to parse the html of it, and get out all of the "src = foo" from all the images in the email. My question is how do I then proceed to create an image using the information taken out from "src" in the of the html. I need this object in order to store it in a sharepoint picture library. Just want to know how to create the image object of the image stored in the html of the email.
Not sure about how to put it in SharePoint, but assuming you have a src in an extractedSrc variable:
WebClient webClient = new WebClient();
webClient.DownloadFile(extractedSrc, localFileName)
I guess there are two basic cases you have to consider, 1. The src attribute points to an external image (ie. image stored on a web site), 2. Src points to an image attached in the email.
For case 1. You need to download the image from the external server and then you can save it in your share point
For case 2. You have to decode the attachment sections of the email to extract the file data and then you can save it to your library
In my scenario I want to download the HTML of a page (any page on the Internet) programaticaly but also I want all of the images in the HTML to be in base64 embedded format (not referenced)
In other words, instead of :
<img src='/images/delete.gif' />
I want the downloaded html to look like this:
<img src="data:image/gif;base64,R0lGODl..." />
This way I don't need to go through the process of storing all images in directories, etc, etc.
Does any of you have any idea how this can be done? Or any plugin to do this efficiently?
Well, you'd need to:
Download the original HTML
Find each img element in the HTML (for instance using the HTML agility pack) and for each one:
If it's already using a data URL, ignore it
Otherwise:
Download the image
Encoded it in Base64 using Convert.ToBase64String
Replace the original img tag with one using the base64 version (either in the original string, or via a DOM representation)
Save the final HTML to disk
Is any of these steps causing you a particular problem? You could potentially make it quicker by downloading the images in parallel, but I'd get a serial version working first.
Instead of using a html page with images as base64 encoded strings in the src attribute you might consider using the MHTML format instead. Most browsers supports the format and it embeds all external resources (including images).
var msg = new CDO.MessageClass();
msg.MimeFormatted = true;
msg.CreateMHTMLBody("http://www.google.com", CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
var stream = msg.GetStream();
var mhtml = stream.ReadText(stream.Size);
Use a regular expression (regex) to extract URLs from img tags, translate them to absolute URLs using the Uri class, then use WebClient to download the target images. After that it's just a case of using Convert.ToBase64String to produce the Base64.