Chas asked:
Thanks for your great series on working with PDFs. I have a question I hope you can help me with. I want to create a PDF (simple enough using cfdocument) but then I would like to email it without having to write it disk using a filename. I can create it and save to "name", but I can't seem to be able to use that in the cfmailparam. Any way to generate a PDF and email it on the fly?
Turns out this is rather simple, if you are using ColdFusion 8.0.1. CF801 added the ability to use cfmailparam to attach files stored in a variable. For example:
<cfdocument format="pdf" name="pdfdoc">
<h1>Snazzy PDF</h1>
Here is your cool PDF that is dynamic: <cfoutput>#randRange(1,100)#</cfoutput>
</cfdocument>
<cfmail to="ray@camdenfamily.com" from="foo@foo.com" subject="Your PDF">
<cfmailparam file="doc.pdf" content="#pdfdoc#">
Attached please find your cool PDF. Enjoy!
</cfmail>
Done.
The first part of the template creates a simple dynamic PDF. Then I mail it to myself. Note that cfmailparam uses both file and content attributes. The content will be the actual data attached to the email while the file attribute will be used for the file name.
In case you are wondering why this isn't in the docs, or why I didn't do this in my 'emailing cfchart' blog post, it is simply the fact that the main docs have not been updated for 8.0.1. You will be able to find this documented, along with everything else new, in the 8.0.1 release notes: http://www.adobe.com/support/documentation/en/coldfusion/releasenotes.html#801
Archived Comments
Ahh, very nice. I hadn't realized this. If you're not running 8.0.1 you could utilize the technique that Dan outlines <a href="http://blog.pengoworks.com/...">here</a>.
Whoops, try this: http://blog.pengoworks.com/...
it has been a couple of years since i worked full-time with coldfusion, but it still just blows me away when i see stuff like this - regular cf devs take this for granted, but you just dynamically generated a pdf file and sent it via email in less than 10 lines of code. I have yet to see another web dev language that could do this (at least without enless lines of behind the scenes configuration).
Regs,
/t
argh!
I needed to do this in a project a couple months back and went to the trouble of using some nasty java class to send the email.
oh well, nice to know for the next time
I'm currently using this method to send pdf's within my company. I'm noticing the memory on the server starting to spike and hold pretty steadily now that word is getting around about my app.
My question is: Do you think it would be beneficial to clear the variable holding that document after its been sent? If so, can you advise on how to best accomplish this?
I'm already dynamically creating a unique "name" (w/in cflock) for the pdf so there would be no problem clearing it if you folks think that would help.
Thanks!
Hmm, if you are generating the same PDF over and over again, it may be better to save it to the file system and use that version for future emails.
Thanks for the reply Ray!
They're all unique reports based on the users selections; however, I lowered the session timeout and that seemed to have mitigated the high memory issue I was running into.
Thanks again, and keep up the amazing work. Your blog has helped me numerous times. I come here when I can't get "out side the box" for a little Coldfusion Jedi insight :)
Brian.
This is really helpful - I need to do something similar, with a twist... in this case the client is a small govt agency. They are developing some simple PDF forms in livecycle, and I'm learning how to integrate the PDF form submission with CF.
If possible, we'd like a user to submit a PDF form in their browser, and then we:
1) save the pdf to the server, looking just like the form they filled out, with their data in place
2) email a copy of same (once saved to server emailing is no problem - that's this blog entry!)
AND
3) extract just the data from the form (ala 'form.variablename' in cf), and save it to a database, separate from the actual PDF layout.
Can it be done?
I am just starting to play with their existing PDF forms and the 'submit' options seem somewhat limited... which makes me think I am missing something.
@ME - Yes, I think you just need to look into cfpdfform. I haven't played with it a lot, but it should allow for this.
as usual, cf says in one tag or command what i couldn't even say very well in 12 lines.
I knew i could 'make' a pdf form with cfpdfform ( #1 below), but didn't realize it did these other things, too. Very cool, thanks.
+++
* Embed an interactive form created in Acrobat LiveCycle in a PDF document. You use the cfpdfform tag to embed the PDF form in a cfdocument tag.
* Render an existing form created in Acrobat or LiveCycle. This includes prefilling fields from a database or an XML data file and processing form data from an HTTP post or PDF submission.
* Extract or prefill values in stored PDF forms and save the output to a file or use it to update a data source.
+++
ps TOO weird. The captcha that came up for this reply was "m e"
So glad I found this - just saved me a ton of work!
So after I tried to implement - I realized that I am using 7 on this server. Is there a similar method - or something like it - that can be used there?
You can send mail with attachments in CF7 - you just can't use an in-memory variable like I did. You would need to save the data to the file system and then clean it up later.
Hi Ray
I am getting the following error when attaching my cfdocument via the cfmailparam tag:
ByteArray objects cannot be converted to strings.
I know the pdf is being generated as I wrote it to desk to check this. My code is as follows:
<cffunction name="sendPDF" output="false" access="public" returntype="struct">
<cfargument name="replyto_name" required="false" type="String" default="">
<cfargument name="replyto_email" required="false" type="String" default="">
<cfargument name="to_name" required="false" type="String" default="Admin">
<cfargument name="to_email" required="false" type="String" default="#application.settings.adminEmail#">
<cfargument name="subject" required="false" type="String" default="Form Email">
<cfargument name="type" required="false" type="String" default="html">
<cfset var thepath = '#ExpandPath("images/giftvoucher/logo.jpg")#'>
<cfset var thepath2 = '#ExpandPath("images/giftvoucher/podplayshop.jpg")#'>
<cfset var logopath = '#ExpandPath("images/logo.jpg")#'>
<cfset result.isSuccess = false>
<cfset result.message = "An unknown error occurred.">
<cfset result.data = "">
<cfset thepath = 'http://www.mydomain.com/tes...
<cfset thepath2 = 'http://www.mydomain.com/tes...
<cfset logopath = 'http://www.mydomain.com/tes...
<cftry>
<!--- CREATE THE PDF --->
<cfdocument format="PDF" name="voucherpdf">
<cfoutput>
<div style="text-align:center;">
<div style="width:700;border:1px solid orange;">
<div style="float:right;width:337px;text-align:left;">
<img src='http://www.mydomain.com/tes... width='337' height='101' />
<img src='http://www.mydomain.com/tes... width='330' height='103' />
<p>side content goes here</p>
</div>
<div style="float:left;text-align:left;">
<p>The main content will go here...</p>
</div>
<br clear="all"/>
</div>
</div>
</cfoutput>
</cfdocument>
<!--- SEND THE MAIL --->
<cfmail to = "#ARGUMENTS.replyto_name#<#ARGUMENTS.replyto_email#>" from = "#application.settings.systemEmail#" subject = "#ARGUMENTS.subject#" server="#application.settings.smtpServer#" username="#application.settings.systemEmail#" password="#application.settings.systemEmailPassword#" type="html" replyto="#ARGUMENTS.to_name#<#ARGUMENTS.to_email#>">
<cfmailparam file='doc.pdf' contentID="#voucherpdf#">
<cfsavecontent variable="theEmail">
<cfoutput>
<center>
<cfmailparam file='#logopath#' contentid='mainlogo' disposition='inline' />
<img src='cid:mainlogo' width='400' height='130' alt='Company Name' />
<p>Attached is your voucher.</p>
<p>Hope you enjoy spending it :)</p>
<p>Kind Regards</p>
</center>
</cfoutput>
</cfsavecontent>
<cfoutput>#theEmail#</cfoutput>
</cfmail>
<cfset result.data = #theEmail#>
<cfcatch>
<cfset result.message = '#cfcatch.message#'>
</cfcatch>
</cftry>
<cfreturn result>
</cffunction>
The code calling this function is:
<cfsilent>
<cfset variables.email = createObject("component","components.utility").sendPDF("MyName",APPLICATION.settings.ownerEmail)>
</cfsilent>
<cfoutput>
#VARIABLES.email.message#
</cfoutput>
Please point me in the right direction.
Thanks in advance
The contentid value of cfmailparam is a string, not binary data.
Ignore my previous post...
I was using 'contentID' instead on 'content'
<cfmailparam file='doc.pdf' contentID="#voucherpdf#">
<cfmailparam file='doc.pdf' content="#voucherpdf#">
I'm using a similor code to send dynamic pdf, i've a strange problem with the image background. The two first pdf contains the images but all the other are not included.
Here is the code i'm using
<cfloop list="#form.fournisseur_id#" index="index">
<cfquery name="Getfournisseur" datasource="#application.dsn#">
SELECT * from fou
WHERE fou_id=#index#
</cfquery>
<cfdocument pagetype="A4" format="pdf" fontembed="yes" backgroundvisible="true" name="annexe">
<cfoutput>
<html>
<head>
<style >
.backgroundimage {
background-image: url(/images/background.gif);
background-repeat: no-repeat;
height:2339px;
width:1654px;
position:absolute;
top:-100px;
visibility: visible;
left: -50px;
z-index: 0;
}
</style>
</head>
<body>
<div class="backgroundimage"></div>
<div style="z-index:1; position:absolute; font-size:33px; padding-left:50px;">
<DIV style="padding-left:1000px; font-weight:bold; padding-top:500px; ">
#getfournisseur.name#<br>
#getfournisseur.adress#<br>
</div>
<p>
#replace(form.contenu,"#chr(13)#","<br>","all")#
</p>
<br><br>
</div>
</body>
</html>
</cfoutput>
</cfdocument>
<cfmail from="#application.from#" to="#getfournisseur.email#" subject="info" type="HTML">
<cfmailparam file="annexe.pdf" content="#annexe#">
</cfmail>
</cfloop>
Hi Ray,
I tried your example and are having an issue opening the PDF file. I get the following Adobe Reader error:
"Adobe Reader could not open 'document.pdf' because it is either not a supported file type or because the file has been damanged (for example, it was sent as an email attachment and wasn't correctly decoded)."
I checked the properties of the file and was listed to have a PDF Version: 0.0 (under the PDF tab).
My Coldfusion Email Client is SmarterMail sending to a GMAIL account, if this makes a difference.
Any suggestions?
Thanks!
Anthony
First - add a line of code to save the PDF binary to the file system. See if the file is ok there.
Ray - Saving the file before attaching it to cfmail seems to be doing the trick, but there is a way to generate the pdf and mail it without saving it? Or is it best practice to first save the file?
Well, I wouldn't save it if you didn't need to. So - let's see why it didn't work for you. Are you running 801? (Note I said 801, not 8.)
Sorry about the late response. I just checked the server and are running version 8,0,1,195765.
Ok, interesting. Um, well wow. I'm out of ideas. :) You can file a bug report with Adobe, but it definitely worked for me. But if your having success with using a 'real' file, for now then I'd just stick with that. Sorry I don't have a better answer.