Adobe ColdFusion 8

Getting Exchange items and attachments

You can get calendar events, contacts, mail messages, and tasks from the Exchange server. You can also get attachments to these items.

Getting an exchange item and its attachments can require multiple operations.

  • To get mail that is not directly in the Inbox, you must specify the path from the root of the mailbox to the mail folder, and you can get items from only a single mail folder at a time. You can use the cfexchangeconnection tag to get the names, paths, and sizes of all folders in a mailbox, and can use the results to iterate over the folders.
  • To get an attachment to an item, you must first get the item, and then use the item UID to get its attachments.
  • If an Exchange item contains a message with inline images, the images are available as attachments. You can get the attachments, use the attachment CID to locate the image in the message, and display the image inline.

Getting and using folder names

To get the names of folders in the mailbox, or the subfolders of a particular folder, use the cfexchangeconnection tag with the getSubfolders action. This action returns a query with a row for each subfolder. The query has three columns:

  • folder name
  • full path from the mailbox to the folder, including the Inbox
  • folder size, in bytes

You can specify the folder whose subfolders you are getting and whether to recursively get all levels of subfolders.

You can use a folder path from the getSubfolders action in the cfexchangemail tag folder attribute to specify the folder that contains the mail message that requires action. If you do not specify a folder, the cfexchangemail tag searches only the top level of the Inbox for the message to be acted on.

To perform operations on mail from multiple folders, including getting mail items or attachments, you can loop over the entries in the query returned by the getSubfolders action, as the following example shows. This example generates a report of all declined meeting messages in the Inbox and all its subfolders.

<!--- Create a connection. --->
<cfexchangeConnection
    action="open"
    username ="#user2#"
    password="#password2#"
    server="#exchangeServerIP#"
    connection="conn1">

<!--- Get the names and paths to all subfolders. --->
<cfexchangeconnection action="getSubfolders" connection="conn1"
    name="folderInfo" folder="Inbox" recurse="yes">

<!--- Get the information from the Inbox top level. 
            The getSubfolders results do not include an Inbox row. --->
    <cfexchangemail action="get" connection="conn1"
            name="theResponses">
        <cfexchangefilter name="MessageType" value="Meeting_Response">
    </cfexchangemail>

<!--- Use a query of queries to select only the declined meetings. --->
<!--- You cannot use cfexchangefilter to filter for the meeting response type. --->
    <cfquery dbtype="query" name="theResponses">
        SELECT * FROM theResponses
        WHERE MEETINGRESPONSE = 'Decline'
    </cfquery>

<!--- Loop through the subfolders and get the meeting responses from each
    folder. --->
<cfloop query="folderInfo">
    <cfexchangemail action="get" connection="conn1"
            name="#folderinfo.foldername#">
        <cfexchangefilter name="folder" value="#folderinfo.folderpath#">
        <cfexchangefilter name="MessageType" value="Meeting_Response">
    </cfexchangemail>
    
    <!--- Use the evaluate function to get the name of the folder. --->
    <cfset meetingData=evaluate(folderinfo.foldername)>
    <!--- Use a query of queries with a UNION clause to add this folder's 
            results to the theResponses query. --->
    <cfquery dbtype="query" name="theResponses">
        SELECT * FROM meetingData
        WHERE MEETINGRESPONSE = 'Decline'
        UNION
        SELECT * FROM theResponses
    </cfquery>
</cfloop>

<!--- Close the connection. --->
<cfexchangeConnection
    action="close"
    connection="conn1">

<!--- Display the results. --->
<h3>The Declined Responses:</h3>
<cftable query="theResponses" colheaders="yes" border="yes">
    <cfcol header="From" text="#FROMID#">
    <cfcol header="Subject" text="#SUBJECT#">
    <cfcol header="Message" text="#MESSAGE#">
</cftable>

Getting items

You get one or more events, contacts, mail messages, or tasks from the Exchange server by using a cfexchangecalendar, cfexchangecontact, cfexchangemail, or cfexchangetask tag, respectively, and specifying an action attribute value of get. ColdFusion returns the items in a query object that you specify in the tag's name attribute. You determine the items to get by specifying selection conditions in cfexchangefilter child tags. The code to get items from the Exchange server has the following pattern:

<cfexchange*** 
        action="get" 
        name="results query object name"
        connection information>
    <cfexchangefilter 
            name="filter type"
            value"filter value>
    <cfexchangefilter 
            name="data/time filter type"
            from="start date/time"
            to="end date/time">
    .
    .
    .
</cfexchange>

The following rules determine how you get items:

  • You can have zero or more cfexchangefilter tags.
    • If you do not specify a maxrows field in the structure specified by the name attribute, ColdFusion gets a maximum of 100 items. To get more items, specify a maxrows field value greater than 100.
    • If you specify multiple cfexchangefilter tags with different name attributes, ColdFusion gets all items that match all of the specified conditions.
    • If you specify multiple cfexchangefilter tags with identical name attributes ColdFusion gets the items that match only the last tag with the duplicate name attribute.
  • The name attributes correspond to field names in the Exchange item records. The valid values for the name attributes depend on the type of item you are getting. For detailed lists of the valid values, see the corresponding tag references in the CFML Reference.
  • If the name attribute specifies a field that takes text or numerical information, you use the value attribute to specify the condition.
  • If the name attribute specifies a field that takes a date, time, or date and time, you use the from and to attributes to specify the range. You can omit one of these attributes to specify an open-ended range, such as all dates up to and including December 1, 2007.
  • Date ranges are inclusive. The selected items include those with the specified to or from dates.
  • You cannot use the empty string as a value attribute to search for an empty value. To find entries where a particular field has an empty value, get all entries and use a query of queries to filter the results to include only entries where the field is empty.
  • In fields that take text strings such as Message and or Subject, ColdFusion returns items that contain the exact phrase that you specify in the value attribute.
  • When you use the cfexchangemail tag, ColdFusion gets only items a single folder. If you include a filter for a folder, ColdFusion gets items that are directly in the Inbox only and does not search any subfolders. For an example of getting information from multiple folders, see Getting and using folder names.

When ColdFusion gets the results, it creates the query object specified in the name attribute, if it does not exist, and populates each row with a single item such as a mail message. The query columns depend on the type of item. For example, a mail message has FromID and ToID fields, and a contact has FirstName and LastName fields. For detailed information on the returned structures, see the corresponding tag in the CFML Reference.

The query results for all types of items have two columns:

  • A UID column with the unique ID of the item. You use this value to specify the item when you delete, modify, or (for calendar entries) respond to it. You also use the UID value to get the item's attachments.
  • A HasAttachments column with a Boolean value specifying whether the item has any attachments. If this field is true, you can use the getAttachments action to get the attachments.

The following example gets the mail messages that were sent during the last week to the docuser1 user from any e-mail address that includes adobe.com. To keep this code short, the example uses the cfdump tag to show the results.

<cfset rightNow = Now()>
<cfset lastWeek = DateAdd("d","-7", rightNow)>

<cfexchangemail action="get" name="weeksMail"
        username ="#user1#" password="#password1#"
        server="#exchangeServerIP#">
    <cfexchangefilter name="FromID" value="adobe.com">
    <cfexchangefilter name="TimeSent" from="#lastWeek#" to="#rightNow#">
</cfexchangemail>

<cfdump var="#weeksMail#">

Getting item attachments

To get the attachments to an Exchange contact, event, message, or task, use a ColdFusion Exchange tag with a getAttachments action. You must also specify the following information in the tag:

  • The UID of the message that contains the attachment or attachments.
  • The name of the query that will contains information about the returned attachments. When the tag completes processing, the query object contains one record for each retrieved attachment. The query has six columns that contain the filename, complete path to the saved attachment file, MIME type, file size, CID value (or an empty string) and an indicator that shows whether the attachment is a message.
  • The path where the attachment is saved. (If you omit the path, ColdFusion does not get the attachments, but does get the information about the attachments.)
  • Optionally, whether to create unique filenames by appending numbers to the names when two or more attachments have the same names. (The default is to not create unique filenames.)

The following ColdFusion Exchange tag gets all attachments to the message identified by the theUID variable, saves them in the C:/temp/cf_files/attachments directory, and stores information about the attachments in the attachInfo structure:

<cfexchangemail action="getattachments"
connection="myconn1" 
uid="#theUID#"
name="#attachInfo#"
attachmentPath="C:/temp/cf_files/attachments"
generateUniqueFilenames="true">

To get a message's attachments, you must have the UID of the message and know that the message has attachments. Use a ColdFusion Exchange tag, such as cfexchangemail, with the get action to determine this information. When the tag completes processing, the query specified by the name attribute includes the following columns:

  • The HasAttachments field is true if a message has one or more attachments
  • The UID field contains the Exchange UID of the item. The exact UID format depends on the type of item; event, contact, message, or task.

You can use these fields in your decision logic that determines whether to get attachments for a message and determines the message UID.

The following example gets the attachments to all mail messages from docuser2 in the last week. It puts each message's attachments in a directory whose name is the hexadecimal part of the message UID. For each message with attachments, the application reports subject and date of the message, followed by a table listing the message's attachments. The table includes the attachment name, MIME type, and size.

Notice that if a message has multiple attachments with the same name, the attachment information query always lists the attachments with their original, duplicate names, even if you specify generateUniqueFilenames="true". The generateUniqueFilenames attribute only affects the names of the files on disk. The attachment information structure's attachmentFilePath column does have the unique filenames, however.

<cfset rightNow = Now()>
<cfset lastWeek = DateAdd("d","-7", rightNow)>

<cfexchangeconnection
    action="open"
    username ="#user1#"
    password="#password1#"
    server="#exchangeServerIP#"
    connection="conn1">
        
<cfexchangemail action="get" folder="Inbox/MailTest" name="weeksMail"
        connection="conn1">
    <cfexchangefilter name="FromID" value="docuser2">
    <cfexchangefilter name="TimeSent" from="#lastWeek#" to="#rightNow#">
</cfexchangemail>

<cfloop query="weeksMail">
    <cfif weeksmail.HasAttachment>
        <!--- The UID is surrounded in <> characters and has an @ character.
        Extract the hexadecimal number part for use as a directory name. --->
        <cfset atpos=Find('@', weeksMail.UID)>
        <cfset shortUID=Mid(weeksMail.UID, 2, atpos-2)>
        
        <cfexchangemail action="getAttachments" 
            connection="conn1"
            folder="Inbox/MailTest"
            uid="#weeksMail.uid#" 
            name="attachData" 
            attachmentPath="C:/temp/cf_files/attachments/#shortUID#"
            generateUniqueFilenames="true">

        <cfoutput>
            Directory #shortUID# contains these attachments to the
            following message:<br />
            Subject: #weeksMail.Subject#<br />
            Sent: #dateFormat(weeksmail.TimeSent)#<br />
            <cftable query="attachData" colheaders="true">
                <cfcol header="Filename" text="#attachmentFilename#">
                <cfcol header="Size" text="#size#">
                <cfcol header="MIME type" text="#mimeType#">
            </cftable>
        </cfoutput>

    </cfif>
</cfloop>

<cfexchangeconnection
    action="close"
    connection="conn1">

Displaying images inline

If an HTML message includes inline images, the Exchange server saves the images as attachments. You must take the following steps to display the images in the retrieved message:

  1. Use cfexchangemail tag get action to get the mail message.
  2. Use cfexchangemail tag getattachments action to get the message attachments. Specify the UID of the mail message you got in the previous step. Also specify an attachmentPath attribute value that is under your web root, so that you can access the saved files by using a URL.
  3. Search through the HTMLMessage field text that you got in step 1 and find the image items. Get the CID (content ID) value for each image.
  4. Search the attachments query that you got in step 1. For each row with a CID column value that you got in step 3, get the corresponding attachmentFilePath column value.
  5. Replace every img tag src attribute value with the attachmentFilePath field value that corresponds to the cid value.
  6. Display the resulting HTML.

The following example shows how to display a message with an inline image by retrieving the image from the attachments.

<!--- Open the connection to the Exchange server. --->
<cfexchangeconnection
    action="open"
    username = "#user1#"
    password = "#password1#"
    server = "#exchangeServerIP#"
    connection = "testconn">
    
<!--- Get the mail message. --->
<cfexchangeMail action="get" connection ="testconn" name="getMail">
    <cfexchangeFilter name="Subject" value="sample inline image">
</cfexchangeMail>

<cfdump var="#getMail#">

<!--- The following code assumes we found only one matching message. --->
<cfoutput query="getMail">
    <cfset theUID = #getMail.UID#>
    <cfset htmlmessage = getMail.htmlmessage>
</cfoutput>

<!--- Get the message's attachments. --->
<CFExchangeMail action="getAttachments" UID ="#theUID#" connection="testconn" name="attachments" attachmentPath="C:\ColdFusion8\wwwroot\My_Stuff\cfexchange\Book\attachments" generateuniquefilenames="no">

<!--- Extract the image names from the mail message --->
<!--- Initialize the index into the message used in finding --->
<cfset findstart = 1>
<!--- Use an index loop to find all image source entries in the message --->
<!--- This example supports up to 25 inline images --->
<cfloop index="i" from="1" to="25">
    <!--- find a cid: entry --->
    <cfset stringStart[i] = Find('"cid:', htmlmessage, findstart)>
    
    <!--- Exit the loop if no match was found --->
    <cfif (stringstart[i] EQ 0)>
        <cfbreak>
    </cfif>
    <!--- Increment the string index used in finding images. --->
    <cfset findstart = stringstart[i] +5 >
    <!--- Get text to the right of ‘cid:.’
        Using a string length of 30 should get more than the image name. --->
    <cfset rightpart[i]=Mid(htmlmessage, findstart, 30)>
    <!--- use the ListFirst function to remove all the text starting 
        at the quotation mark. --->
    <cfset imagename[i]=ListFirst(rightpart[i], '"')>

    <!--- Loop over the attachments query and find the CID. --->
    <cfloop query="attachments">
        <!--- Replace the image name with the contents of the attachment --->
        <cfif attachments.CID EQ imagename[i]>
            <cfset htmlmessage = Replace(htmlmessage,"cid:#imagename[i]#", 
            "attachments/#attachments.ATTACHMENTFILENAME#")>
        </cfif>
    </cfloop>
</cfloop>

<h3>The full mail message</h3>
<cfoutput>#htmlmessage#</cfoutput>

<cfexchangeconnection
    action="close"
    connection = "testconn">