I've used ABDpdf to render a pdf and stream it to the browser, but I'm wondering if I can attach the rendered pdf to an email. Has anyone ever done that?
I'm hoping there is a way that doesn't require me to save the pdf to a temp directory then attach the file, then delete it.
Meklarian is right, but one little thing to point out, is that after you've saved the pdf into your stream, you will want to reset your stream position back to 0. Otherwise the attachment that is sent will be all foo-barred.
(It took me about two hours to figure it out. Ouch. Hope to help someone else save some time.)
//Create the pdf doc
Doc theDoc = new Doc();
theDoc.FontSize = 12;
theDoc.AddText("Hello, World!");
//Save it to the Stream
Stream pdf = new MemoryStream();
theDoc.Save(pdf);
theDoc.Clear();
//Important to reset back to the begining of the stream!!!
pdf.Position = 0;
//Send the message
MailMessage msg = new MailMessage();
msg.To.Add("you#you.com");
msg.From = new MailAddress("me#me.com");
msg.Subject = "Hello";
msg.Body = "World";
msg.Attachments.Add(new Attachment(pdf, "MyPDF.pdf", "application/pdf"));
SmtpClient smtp = new SmtpClient("smtp.yourserver.com");
smtp.Send(msg);
According to the documentation on the ABCpdf PDF support site, there is an overload of the Doc() object that supports saving to a stream. With this feature, you can save the results a generated PDF without explicitly writing to disk by using the MemoryStream class.
ABCpdf PDF Component for .NET : Doc.Save()
MemoryStream (System.IO) # MSDN
With a MemoryStream created, you may then pass the stream on to any email provider that supports creating attachments from a stream. MailMessage in System.Net.Mail has support for this.
MailMessage Class (System.Net.Mail) # MSDN
MailMessage.Attachments Property # MSDN
Attachments Class # MSDN
Attachments Constructor # MSDN
Finally, if you've never used the MailMessage class before, use the SmtpClient class to send your message on its way.
SmtpClient Class (System.Net.Mail)
Related
I'm using HttpSelfHostConfiguration to create a WebAPI (service). My goal is to have one route stream the mjpeg video from a security feed and have other routes available for configuration and the web interface.
The issue I'm having is that every example I've come across expects a known quantity of images in order to set the content-length for the main response. I don't have this, and flushing the stream doesn't do anything.
Here's the current code for the response. If I use this same code with raw sockets instead of through an ApiController, I can stream it just fine, but creating a webserver from scratch for everything else I'm needing doesn't seem like a lot of fun.
[HttpGet]
public HttpResponseMessage Stream(int channel)
{
var response = Request.CreateResponse();
response.Content = new PushStreamContent((outputStream, content, context) =>
{
StreamWriter writer = new StreamWriter(outputStream);
while (true)
{
using (MemoryStream ms = new MemoryStream())
{
ReadMemoryMappedFile(channel);
ms.SetLength(0);
this.Image.Bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] buffer = ms.GetBuffer();
writer.WriteLine("--boundary");
writer.WriteLine("Content-Type: image/jpeg");
writer.WriteLine(string.Format("Content-length: {0}", buffer.Length));
writer.WriteLine();
writer.Write(buffer);
writer.Flush();
}
}
});
response.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/x-mixed-replace; boundary=--boundary");
return response;
}
I hope my late answer will help, since I ran into the same issue recently and it took me some time to figure it out...
My solution was to specify the boudary int the ContentType without the "--" (but you need to keep them while writing in the stream).
Try to configure the Headers like that :
response.Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("multipart/x-mixed-replace; boundary=boundary");
And write boundaries in the stream like that :
writer.WriteLine("--boundary");
Like this it works for me.
I couldn't find anywhere that explicitly states this, but I'm going to assume that HttpSelfHostConfiguration does not support the functionality I'm looking for, and always requires the stream to be closed before it will release the buffer.
I swapped HttpSelfHostConfiguration with OWIN.SelfHost and it works as expected.
We are reading the adobe form template using ABCpdf , populating form fields with values retrieved from database and amending them into a single PDF document and sending the document back as File stream in the HTTP response to the users in a ASP.net MVC App.
This approach is working fine and PDF documents are getting generated successfully. But when the user choose to open the generated PDF file and try to close it, they are being prompted ‘Do you want to save changes to xxx.pdf before closing’ dialog from Adobe Acrobat. Is there any way of suppressing this message using ABC pdf?.
Following is the code we are using to generate the PDF.
public byte[] GeneratePDF(Employee employee, String TemplatePath)
{
string[] FieldNames;
Doc theDoc;
MemoryStream MSgeneratedPDFFile = new MemoryStream();
//Get the PDF Template and read all the form fields inside the template
theDoc = new Doc();
theDoc.Read(HttpContext.Current.Server.MapPath(TemplatePath));
FieldNames = theDoc.Form.GetFieldNames();
//Navigate through each Form field and populate employee details
foreach (string FieldName in FieldNames)
{
Field theField = theDoc.Form[FieldName];
switch (FieldName)
{
case "Your_First_Name":
theField.Value = employee.FirstName;
break;
default:
theField.Value = theField.Name;
break;
}
//Remove Form Fields and replace them with text
theField.Focus();
theDoc.Color.String = "240 240 255";
theDoc.FillRect();
theDoc.Rect.Height = 12;
theDoc.Color.String = "220 0 0";
theDoc.AddText(theField.Value);
theDoc.Delete(theField.ID);
}
return theDoc.GetData();
}
Today I ran into this problem too, but with a PDF with no form fields. I ran #CharlieNoTomatoes code and confirmed the FieldNames collection was definitely empty.
I stepped through the various stages of my code and found that if I saved the PDF to the file system and opened from there it was fine. Which narrowed it down to the code that took the abcpdf data stream and sent it directly to the user (I normally don't bother actually saving to disk). Found this in the WebSuperGoo docs and it suggested my server might be sending some extra rubbish in the Response causing the file to be corrupted.
Adding Response.End(); did the trick for me. The resulting PDF files no longer displayed the message.
byte[] theData = _thisPdf.Doc.GetData();
var curr = HttpContext.Current;
curr.Response.Clear();
curr.Response.ContentType = "application/pdf";
curr.Response.AddHeader("Content-Disposition", "attachment; filename=blah.pdf");
curr.Response.Charset = "UTF-8";
curr.Response.AddHeader("content-length", theData.Length.ToString());
curr.Response.BinaryWrite(theData);
curr.Response.End();
I ran into this problem, as well. I found a hint about "appearance streams" here:
The PDF contains form fields and the NeedAppearances entry in the interactive form dictionary is set to true. This means that the conforming PDF reader will generate an appearance stream where necessary for form fields in the PDF and as a result the Save button is enabled. If the NeedAppearances entry is set to false then the conforming PDF reader should not generate any new appearance streams. More information about appearance streams in PDF files and how to control them with Debenu Quick PDF Library.
So, I looked for "appearance" things in the websupergoo doc and was able to set some form properties and call a field method to get rid of the "Save changes" message. In the code sample above, it would look like this:
Edit: After exchanging emails with fast-and-helpful WebSuperGoo support about the same message after creating a PDF with AddImageHtml that WASN'T fixed by just setting the form NeedAppearances flag, I added the lines about Catalog and Atom to remove the core document NeedAppearances flag that gets set during AddImageHtml.
public byte[] GeneratePDF(Employee employee, String TemplatePath)
{
string[] FieldNames;
Doc theDoc;
MemoryStream MSgeneratedPDFFile = new MemoryStream();
//Get the PDF Template and read all the form fields inside the template
theDoc = new Doc();
theDoc.Read(HttpContext.Current.Server.MapPath(TemplatePath));
FieldNames = theDoc.Form.GetFieldNames();
//Tell PDF viewer to not create its own appearances
theDoc.Form.NeedAppearances = false;
//Generate appearances when needed
theDoc.Form.GenerateAppearances = true;
//Navigate through each Form field and populate employee details
foreach (string FieldName in FieldNames)
{
Field theField = theDoc.Form[FieldName];
switch (FieldName)
{
case "Your_First_Name":
theField.Value = employee.FirstName;
break;
default:
theField.Value = theField.Name;
break;
}
//Update the appearance for the field
theField.UpdateAppearance();
//Remove Form Fields and replace them with text
theField.Focus();
theDoc.Color.String = "240 240 255";
theDoc.FillRect();
theDoc.Rect.Height = 12;
theDoc.Color.String = "220 0 0";
theDoc.AddText(theField.Value);
theDoc.Delete(theField.ID);
}
Catalog cat = theDoc.ObjectSoup.Catalog;
Atom.RemoveItem(cat.Resolve(Atom.GetItem(cat.Atom, "AcroForm")), "NeedAppearances");
return theDoc.GetData();
}
My project is almost done, and thanks to stackoverflow. Now that I have managed to capture Users details and their certificates, I am looking for a way to generate pdf which I will send to those who passed.
I am not looking for the code at the moment. I have an asp.net mvc 3 application which shows Certificates details for my students. Now I want the certificates to be generated then sent by email, all this automated.
First I would like help on how I can generate a pdf from database values and sending the generated pdf wont be a problem.
Using iTextSharp, this code will create and serve a PDF:
public FileStreamResult DownloadPDF()
{
MemoryStream workStream = new MemoryStream();
using(Document document = new Document())
{
PdfWriter.GetInstance(document, workStream).CloseStream = false;
document.Open();
document.SetPageSize(PageSize.LETTER);
document.SetMargins(12, 12, 8, 7);
document.NewPage();
// Create a new Paragraph object with the text, "Hello, World!"
var welcomeParagraph = new Paragraph("Hello, World!");
// Add the Paragraph object to the document
document.Add(welcomeParagraph);
// This is where your data would go
document.Close();
}
workStream.Position = 0;
FileStreamResult fileResult = new FileStreamResult(workStream, "application/pdf");
fileResult.FileDownloadName = "test.pdf";
return fileResult;
}
For more information see Creating PDF Documents with ASP.NET and iTextSharp
There are a lot of tutorials online, but this should get you started.
I am looking for a sample code on how to forward an existing email message (one that is already in my inbox) using the managed api.
When forwarded is there some way to keep a message original headers while forwarding it?
for example someone sent an email to me -i would like that ews will forward it to another recipient without changing the headers (original receive time from ,bcc etc...).
Given an EmailMessage object, you can just call the CreateForwareMessage() method:
var forwareMessage = item.CreateForward();
Regarding the other question: Get the MIME content of the mail and attach it to a new message:
item.Load(new PropertySet(BasePropertySet.IdOnly, ItemSchema.MimeContent));
var mail = new EmailMessage(service);
var attachment = mail.Attachments.AddFileAttachment("Original message.eml", item.MimeContent.Content);
attachment.ContentType = string.Format("message/rfc822; charset={0}", item.MimeContent.CharacterSet);
mail.ToRecipients.Add("hkrause#infinitec.de");
mail.Subject = "testmail";
mail.SendAndSaveCopy();
EDIT:
Create forward message and set reply to header:
var fw = item.CreateForward();
var fwMsg = fw.Save(WellKnownFolderName.Drafts);
fwMsg.ReplyTo.Add("personA#company.com");
fwMsg.SendAndSaveCopy();
I have an existing PDF and I can use FdFWriter to input to text boxes. It works well. Now I have an image. I have read the documentation and looked at many examples but they all create new documents and insert an image. I want to take an existing PDF and insert an image into either an image field or as the icon image of a button. I have tried but it corrupts the document.
I need to be able to take an existing document and put an image on it. I do not want to open, read, replace, and delete the original. This original changes and the name "original" only means the source file in this context. There are many PDF files like this that need an image.
Thank you for any help.
Edit - I am very thankful for the code below. It works great, but the problem for me is that the existing PDF has digital signatures on it. When the document is copied like this (into result.pdf) those signatures, while still present, have a different byte count or other item that is corrupted. This means the signatures, while they show up on result.pdf, have an icon next to them that state "invalid signature."
In case it matters I am using a Topaz signature pad to create my signatures, which has it's own security. Merely copying the PDF will not corrupt it but the process below will.
I am trying to put the image on the existing document, not a copy of it, which in this case matters.
Also, by signature, I mean handwritten, not pin numbers.
Thank you again.
EDIT - Can PdfSignatureAppearance be used for this?
EDIT - I seem to be able to do it with:
var stamper = new PdfStamper(reader, outputPdfStream,'1',true);
If you want to change the contents of an existing PDF file and add extra content such as watermarks, pagenumbers, extra headers, PdfStamper is the object you need. I have successfully used the following code to insert an image into an existing pdf file to a given absolute position:
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
class Program
{
static void Main(string[] args)
{
using (Stream inputPdfStream = new FileStream("input.pdf", FileMode.Open, FileAccess.Read, FileShare.Read))
using (Stream inputImageStream = new FileStream("some_image.jpg", FileMode.Open, FileAccess.Read, FileShare.Read))
using (Stream outputPdfStream = new FileStream("result.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
{
var reader = new PdfReader(inputPdfStream);
var stamper = new PdfStamper(reader, outputPdfStream);
var pdfContentByte = stamper.GetOverContent(1);
Image image = Image.GetInstance(inputImageStream);
image.SetAbsolutePosition(100, 100);
pdfContentByte.AddImage(image);
stamper.Close();
}
}
}
When you insert the image you have the possibility to resize it. You can take a look at transformation matrix in the iTextSharp documentation.
Here is a similar example whichi inserts an image on the page using the stamper:
Gmane iTex Mailing List Post
I could solve my problem by simply adding following lines to my signing code to add image
var image = iTextSharp.text.Image.GetInstance(#"C:\Users\sushil\Documents\sansign.jpg");
appearance.Acro6Layers = true;
appearance.SignatureGraphic = image;
appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION;
As I was signing document with visible digital signature , now I can have both image and digital signature properties side by side
in the .net core6 that uses DDD try this declare class in Infrastructure Layer
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
public async Task<string> SignatureToPdf(string pathPdfFile, string
pathSignatureImage, string pathOutputName)
{
var webRootPath = hostingEnvironment.ContentRootPath;
if (!File.Exists(Path.Combine(webRootPath, pathPdfFile))) return
null;
await using Stream inputPdfStream =
new FileStream(Path.Combine(webRootPath, pathPdfFile),
FileMode.Open, FileAccess.Read, FileShare.Read);
await using Stream inputImageStream =
new FileStream(Path.Combine(webRootPath, pathSignatureImage), FileMode.Open, FileAccess.Read, FileShare.Read);
await using Stream outputPdfStream =
new FileStream(Path.Combine(webRootPath, pathOutputName),
FileMode.Create, FileAccess.Write, FileShare.None);
var reader = new PdfReader(inputPdfStream);
var stamper = new PdfStamper(reader, outputPdfStream);
var pdfContentByte = stamper.GetOverContent(1);
var image = Image.GetInstance(inputImageStream);
image.SetAbsolutePosition(100, 100);
pdfContentByte.AddImage(image);
stamper.Close();
return "ok";
}
pdftk can do this. It's not a library but you can easily call it from your code as a .exe.
See stamp and background commands:
http://www.pdflabs.com/docs/pdftk-man-page/
ref: How to do mail merge on top of a PDF?