SalesForce Visualforce邮件模板:按联系人发送对应PDF内容技术求助
解决方案:按联系人生成个性化PDF邮件
1. 重构数据结构:用Map关联联系人与参与者
嵌套列表不好直接对应联系人与参与者的关系,建议转成Map<Contact, List<Participant__c>>,这样能直接通过联系人拿到对应的参与者列表。可以通过子查询获取数据后构建映射:
// 查询目标联系人及其关联的参与者(假设Participant__c的Lookup字段为Contact__c) List<Contact> contactsWithParticipants = [ SELECT Id, Name, Email, (SELECT Id, Name, Event__c, Status__c FROM Participants__r) FROM Contact WHERE Email != NULL AND Id IN :yourTargetContactIds // 替换为你的目标联系人ID集合 ]; // 构建联系人到参与者的映射 Map<Contact, List<Participant__c>> contactToParticipantsMap = new Map<Contact, List<Participant__c>>(); for(Contact c : contactsWithParticipants) { contactToParticipantsMap.put(c, c.Participants__r); }
2. 为每个联系人单独生成PDF与个性化邮件
循环遍历映射中的每个键值对,针对每个联系人完成以下操作:生成专属PDF、构建个性化正文、添加附件并创建邮件,最后批量发送。
Apex核心代码示例
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>(); for(Contact c : contactToParticipantsMap.keySet()) { List<Participant__c> participants = contactToParticipantsMap.get(c); // 生成Visualforce PDF PageReference pdfPage = Page.YourParticipantPDFPage; // 替换为你的VF页面API名称 pdfPage.getParameters().put('contactId', c.Id); // 传递联系人ID给VF页面 pdfPage.setRedirect(true); Blob pdfBlob; try { pdfBlob = pdfPage.getContentAsPDF(); } catch(Exception e) { System.debug('生成PDF失败:' + e.getMessage()); continue; // 跳过当前联系人,处理下一个 } // 创建PDF附件 Messaging.EmailFileAttachment pdfAttachment = new Messaging.EmailFileAttachment(); pdfAttachment.setFileName(c.Name + '_关联参与者信息.pdf'); pdfAttachment.setBody(pdfBlob); pdfAttachment.setContentType('application/pdf'); // 构建个性化邮件正文 String emailBody = '亲爱的' + c.Name + ':\n\n'; emailBody += '以下是与您关联的参与者信息,详细内容请查看附件PDF:\n'; // 在正文添加参与者摘要(可选) for(Participant__c p : participants) { emailBody += '- ' + p.Name + '(活动:' + p.Event__r.Name + ',状态:' + p.Status__c + ')\n'; } emailBody += '\n感谢您的关注!'; // 创建单条邮件 Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); email.setToAddresses(new List<String>{c.Email}); email.setSubject('您的关联参与者信息'); email.setPlainTextBody(emailBody); email.setFileAttachments(new List<Messaging.EmailFileAttachment>{pdfAttachment}); emails.add(email); } // 批量发送邮件(注意Salesforce每日邮件发送限制) if(!emails.isEmpty()) { Messaging.sendEmail(emails); }
3. 配置Visualforce页面渲染单个联系人的参与者信息
VF页面需接收contactId参数,查询对应参与者并渲染PDF内容:
<apex:page renderAs="pdf" controller="ParticipantPDFController" applyHtmlTag="false" applyBodyTag="false"> <html> <head> <style type="text/css"> body { font-family: Arial, sans-serif; } .header { text-align: center; margin-bottom: 20px; } .participant-table { width: 100%; border-collapse: collapse; } .participant-table th, .participant-table td { border: 1px solid #ccc; padding: 8px; text-align: left; } </style> </head> <body> <div class="header"> <h1>{!contact.Name} 关联参与者信息</h1> <p>生成时间:{!NOW()}</p> </div> <table class="participant-table"> <tr> <th>参与者姓名</th> <th>关联活动</th> <th>状态</th> <th>创建日期</th> </tr> <apex:repeat value="{!participants}" var="p"> <tr> <td>{!p.Name}</td> <td>{!p.Event__r.Name}</td> <td>{!p.Status__c}</td> <td>{!p.CreatedDate}</td> </tr> </apex:repeat> </table> </body> </html> </apex:page>
对应的VF控制器ParticipantPDFController:
public class ParticipantPDFController { public Contact contact { get; set; } public List<Participant__c> participants { get; set; } public ParticipantPDFController() { String contactId = ApexPages.currentPage().getParameters().get('contactId'); if(String.isNotBlank(contactId)) { contact = [SELECT Id, Name FROM Contact WHERE Id = :contactId LIMIT 1]; participants = [SELECT Id, Name, Event__r.Name, Status__c, CreatedDate FROM Participant__c WHERE Contact__c = :contactId]; } } }
关键注意事项
- 邮件限制:Salesforce有每日邮件发送数量上限,批量发送时需控制单次发送量,避免触发限制。
- 权限检查:确保执行Apex的用户拥有Visualforce页面、Contact和Participant__c对象的访问权限,否则会生成空白PDF。
- 错误处理:代码中加入了PDF生成失败的捕获逻辑,实际使用可根据需求添加日志记录或错误通知。
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

