Property | Description |
---|---|
Autonumber | The API creates an autonumber. |
Create | Value for the field can be specified during create using the API. |
Defaulted on create | When created, a default value is supplied if no other value is specified. |
Delete | Value for the field can be deleted using the API. |
Filter | Can be used as filter criteria in a SOQL query FROM or WHERE clause. |
idLookup | Can be used to specify a record in an upsert() call. The Id field of each object has this property and some Name fields. There are exceptions, so check for the property in any object you wish to upsert(). |
Nillable | The field can contain a null value. |
Query | The field can be queried with SOQL using the API. |
Replicate | The value of the field can be replicated using the API. |
Restricted picklist | A picklist that depends on the value of another picklist for the values it displays. |
Retrieve | Value of the field can be retrieved using the API. |
Search | Can be searched with SOSL using the API. |
Update | Can be updated using the API. |
- Show the email subject, but make that a hyperlink to the email message itself
- Link the Case Number (EmailMessage.ParentId) to the Case (EmailMessage.Parent)
- Show the Case Contact (EmailMessage.Parent.Contact.Name), linking to the Contact (EmailMessage.Parent.ContactId)
- Show the Case Account (EmailMessage.Parent.Account.Name), linking to the Account (EmailMessage.Parent.AccountId)
- Provide filters - Incoming only, Unread only, etc.
public with sharing class EmailMessageController { public String EmailMessage { get; set; } private List<EmailMessage> messages; private String sortDirection = 'ASC'; private String sortExp = 'MessageDate'; public String wheretext; public EmailMessageController(){ wheretext = ''; } public String sortExpression { get { return sortExp; } set { //if the column is clicked on then switch between Ascending and Descending modes if (value == sortExp) sortDirection = (sortDirection == 'ASC')? 'DESC' : 'ASC'; else sortDirection = 'ASC'; sortExp = value; } } public void setWhereText(String value) { whereText = value; } public string getWhereText(){ return wheretext; } public List<SelectOption> getViews(){ List<SelectOption> options = new List<SelectOption>(); options.add(new SelectOption('WHERE e.id != null','All')); options.add(new SelectOption('WHERE e.Incoming = true AND e.Status = '0' ','Incoming Unread')); options.add(new SelectOption('WHERE e.Incoming = true AND e.Status = '1' ','Incoming Read')); options.add(new SelectOption('WHERE e.Incoming = true','All Incoming')); options.add(new SelectOption('WHERE e.Incoming = false','All Outgoing')); options.add(new SelectOption('WHERE e.ToAddress = 'support@x2od.com'','Support Queue')); options.add(new SelectOption('WHERE e.ToAddress = 'support2@x2od.com'','Support Queue2')); //etc. return options; } public String getSortDirection() { //if not column is selected if (sortExpression == null || sortExpression == '') return 'ASC'; else return sortDirection; } public void setSortDirection(String value) { sortDirection = value; } public List<EmailMessage> getMessages() { return messages; } public PageReference ViewData() { //build the full sort expression string sortFullExp = sortExpression + ' ' + sortDirection; //query the database based on the sort expression messages = Database.query('Select e.FromAddress, e.Parent.ContactId, e.Parent.Contact.Name, e.Parent.Account.Name, e.ToAddress, e.Parent.CaseNumber, e.Parent.AccountId, e.TextBody, e.SystemModstamp, e.Subject, e.Status, e.ParentId, e.MessageDate, e.LastModifiedDate, e.LastModifiedById, e.IsDeleted, e.Incoming, e.Id, e.HtmlBody, e.Headers, e.HasAttachment, e.FromName, e.CreatedDate, e.CreatedById, e.CcAddress, e.BccAddress, e.ActivityId From EmailMessage e ' + wheretext + ' order by ' + sortFullExp + ' limit 1000'); return null; } }And here's the Visualforce Page:
<apex:page controller="EmailMessageController" action="{!ViewData}"> <apex:sectionHeader title="Email Messages" subtitle=""></apex:sectionHeader> <apex:pageblock id="emailblock"> <apex:facet name="header"> <apex:form> <apex:panelGrid styleClass="list" columnClasses="pbTitle,pbButton,pbHelp" columns="3" border="0" cellpadding="0" cellspacing="0"> <apex:outputLabel> <h3>Messages</h3> </apex:outputLabel> <apex:commandButton value=" Refresh " styleClass="btn" action="{!ViewData}" rerender="emailblock"></apex:commandButton> <apex:SelectList value="{!wheretext}" size="1" id="controllerselectlist"> <apex:actionSupport event="onchange" action="{!ViewData}" reRender="emailblock"></apex:actionSupport> <apex:selectOptions value="{!views}" /> </apex:SelectList> </apex:panelGrid> </apex:form> </apex:facet> <apex:form> <apex:pageblocktable value="{!Messages}" var="e" id="emailtable" bgcolor="#F3F3EC" styleClass="list" rowClasses="dataRow" onRowMouseOver="hiOn(this);" onRowMouseOut="hiOff(this);"> <apex:column> <apex:facet name="header"> <apex:commandLink action="{!ViewData}" value="{!$ObjectType.EmailMessage.fields.Subject.label}{!IF(sortExpression=='Subject', IF(sortDirection='ASC','▼','▲'),'')}"> <apex:param value="Subject" name="column" assignTo="{!sortExpression}"></apex:param> </apex:commandLink> </apex:facet> <apex:outputLink value="/{!e.Id}" target="_blank">{!e.Subject}</apex:outputLink> </apex:column> <apex:column> <apex:facet name="header"> {!$ObjectType.Contact.fields.Name.label} </apex:facet> <apex:outputLink value="/{!e.Parent.ContactId}" target="_blank" rendered="{!IF(e.Parent.ContactId != '',true,false)}">{!e.FromName}</apex:outputLink> <apex:outputtext value="{!e.FromName}" rendered="{!IF(e.Parent.ContactId != '',false,true)}" /> </apex:column> <apex:column> <apex:facet name="header"> {!$ObjectType.Account.fields.Name.label} </apex:facet> <apex:outputLink value="/{!e.Parent.AccountId}" target="_blank">{!e.Parent.Account.Name}</apex:outputLink> </apex:column> <apex:column value="{!e.FromAddress}"> <apex:facet name="header"> <apex:commandLink action="{!ViewData}" value="{!$ObjectType.EmailMessage.fields.FromAddress.label}{!IF(sortExpression=='FromAddress', IF(sortDirection='ASC','▼','▲'),'')}"> <apex:param value="FromAddress" name="column" assignTo="{!sortExpression}"></apex:param> </apex:commandLink> </apex:facet> </apex:column> <apex:column value="{!e.Status}"> <apex:facet name="header"> <apex:commandLink action="{!ViewData}" value="{!$ObjectType.EmailMessage.fields.Status.label}{!IF(sortExpression=='Status', IF(sortDirection='ASC','▼','▲'),'')}"> <apex:param value="Status" name="column" assignTo="{!sortExpression}"></apex:param> </apex:commandLink> </apex:facet> </apex:column> <apex:column value="{!e.MessageDate}"> <apex:facet name="header"> <apex:commandLink action="{!ViewData}" value="{!$ObjectType.EmailMessage.fields.MessageDate.label}{!IF(sortExpression=='MessageDate', IF(sortDirection='ASC','▼','▲'),'')}"> <apex:param value="MessageDate" name="column" assignTo="{!sortExpression}"></apex:param> </apex:commandLink> </apex:facet> </apex:column> <apex:column value="{!e.Incoming}"> <apex:facet name="header"> <apex:commandLink action="{!ViewData}" value="{!$ObjectType.EmailMessage.fields.Incoming.label}{!IF(sortExpression=='Incoming', IF(sortDirection='ASC','▼','▲'),'')}"> <apex:param value="Incoming" name="column" assignTo="{!sortExpression}"></apex:param> </apex:commandLink> </apex:facet> </apex:column> <apex:column value="{!e.HasAttachment}"> <apex:facet name="header"> <apex:commandLink action="{!ViewData}" value="{!$ObjectType.EmailMessage.fields.HasAttachment.label}{!IF(sortExpression=='HasAttachment', IF(sortDirection='ASC','▼','▲'),'')}"> <apex:param value="HasAttachment" name="column" assignTo="{!sortExpression}"></apex:param> </apex:commandLink> </apex:facet> </apex:column> <apex:column> <apex:facet name="header"> <apex:commandLink action="{!ViewData}" value="{!$ObjectType.Case.fields.CaseNumber.label}{!IF(sortExpression=='ParentId', IF(sortDirection='ASC','▼','▲'),'')}"> <apex:param value="ParentId" name="column" assignTo="{!sortExpression}"></apex:param> </apex:commandLink> </apex:facet> <apex:outputLink value="/{!e.ParentId}">{!e.Parent.CaseNumber}</apex:outputLink> </apex:column> <apex:column value="{!e.ToAddress}"> <apex:facet name="header"> <apex:commandLink action="{!ViewData}" value="{!$ObjectType.EmailMessage.fields.ToAddress.label}{!IF(sortExpression=='ToAddress', IF(sortDirection='ASC','▼','▲'),'')}"> <apex:param value="ToAddress" name="column" assignTo="{!sortExpression}"></apex:param> </apex:commandLink> </apex:facet> </apex:column> </apex:pageblocktable> </apex:form> </apex:pageblock> </apex:page>There are some other cool bits: If there is no Case.Contact, the table will display the FromName, pulled from the email message. An interesting point: You may notice that EmailStatus is presented in numerical form. For instance, Incoming Unread is 0, Incoming Read is 1, etc. The documentation, however, says, "Read only. The status of the email. For example, “New,” “Unread,” “Replied,” “Sent.”" So we're not sure of the exact mapping. 3 seems to be Sent, so 2 is probably Replied... but we're not sure. Don't forget: EmailMessage has two lookups (foreign key): Case, and Activity. This Activity is the task created when Salesforce receives the email, and is - according to the documentation - assigned to the Case Owner. We're not sure what happens when the Case is owned by a Queue. Feel free to comment and share your experiences. That's it! Enjoy.
Jon Mountjoy says
Can you include a screenshot of the app? How about a link to it running on Sites on a Developer Edition? :-)
Kyle Roche says
Nice job David. I’d be interested in the screenshot / link as well. Good stuff.