我该如何从Cocoa发送HTML电子邮件?

6

我正在寻找一种从OS X Cocoa应用程序创建HTML格式电子邮件的方法。

我的首选工作流程是:用户选择菜单项,然后默认的邮件应用程序会打开一个预填充的新电子邮件在前台。

对于纯文本电子邮件,我可以使用mailto和-[NSWorkspace openURL]来实现此操作,但对于HTML电子邮件则无法使用。


一些资源:http://cocoaheads.byu.edu/resources/email - Dave DeLong
这个问题有任何最新消息吗? - Max Seelemann
3个回答

10

我也对此很感兴趣,于是我花了两天时间进行反向工程,使Safari的“邮件此页面内容”功能得以正常使用。

更新: 我改进了代码,并将其放在GitHub上。

- (void)mailWebArchive:(WebArchive *)webArchive title:(NSString *)aTitle URL:(NSString *)aURL {
NSString *bundleID = @"com.apple.mail";
NSData* targetBundleID = [bundleID dataUsingEncoding:NSUTF8StringEncoding];
NSAppleEventDescriptor *targetDescriptor = nil;
NSAppleEventDescriptor *appleEvent = nil;

targetDescriptor = [NSAppleEventDescriptor descriptorWithDescriptorType:typeApplicationBundleID
                                                                   data:targetBundleID];
appleEvent = [NSAppleEventDescriptor appleEventWithEventClass:'mail'
                                                      eventID:'mlpg'
                                             targetDescriptor:targetDescriptor
                                                     returnID:kAutoGenerateReturnID
                                                transactionID:kAnyTransactionID];
[appleEvent setParamDescriptor:[NSAppleEventDescriptor descriptorWithDescriptorType:'tdta'
                                                                               data:[webArchive data]]
                    forKeyword:'----'];
[appleEvent setParamDescriptor:[NSAppleEventDescriptor descriptorWithString:aTitle]
                    forKeyword:'urln'];
[appleEvent setParamDescriptor:[NSAppleEventDescriptor descriptorWithString:aURL]
                    forKeyword:'url '];


NSAppleEventDescriptor *replyDescriptor = nil;
NSAppleEventDescriptor *errorDescriptor = nil;
AEDesc reply = { typeNull, NULL };  

// Send the AppleEvent
OSStatus status = AESendMessage([appleEvent aeDesc],
                    &reply,
                    kAEWaitReply,
                    kAEDefaultTimeout);
if(status == noErr)
{
    replyDescriptor = [[[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&reply] autorelease];
    errorDescriptor = [replyDescriptor paramDescriptorForKeyword:keyErrorNumber];
    if(errorDescriptor != nil)
        status = [errorDescriptor int32Value];

    if(status != noErr)
        NSLog(@"%s error %d", _cmd, status);
}
}

这段代码没有检查邮件是否正在运行,所以只有在邮件已经启动时才能正常工作。
这种方法的优点是它适用于所有实现MailLinkSupported和MailPageSupported的电子邮件客户端。请参见QA1722
缺点是您无法像使用mailto那样设置收件人。对此,脚本桥似乎是唯一的解决方案。请参见这个修改后的SBSendEmail样例

谢谢Chris。在ATMailHelper方法中,baseURL是什么? - lostInTransit
一个用于解析文档中相对URL的文件。如果你的HTML邮件包含未从网络下载的图片,你需要它。 - catlan
我没有任何图片。那我应该放什么?注意到如果没有baseURL,WebResource就不会被创建。 - lostInTransit
字典的路径,其中包含HTML输出。如果您在运行时生成HTML,请尝试使用任何有效的路径(捆绑资源等)。 - catlan
你好。在这种情况下如何设置收件人?谢谢。 - Vitalya
使用 NSURL *mailURL = [NSURL fileURLWithPath:path]; 而不是 NSURL *mailURL = [NSURL URLWithString:path]; 因为第二种情况中URL没有方案,这会导致Apple事件失败。 - Raunak

3

没有标准的方法可以与任意电子邮件客户端进行复杂的交互。您需要分别处理要支持的每个应用程序,并查看它是否有设置电子邮件格式的方式--最可能是通过Applescript--然后检测默认的mailto处理程序并运行适当的代码。对于某些电子邮件客户端,这可能是不可能的(就像某些客户端没有支持的方法来打开一个带附件的新电子邮件一样)。


在互联网上进行了广泛的搜索后,我基本上得出了相同的结论。目前,我正在尝试通过脚本桥接实现仅使用Mail.app的解决方案,但到目前为止,我未能将富文本/HTML设置为邮件内容。如果我找到解决方案,我会将其添加到这个问题中。 - Markus Müller-Simhofer

0

Dustin Bachrach在这里发布了一个优雅(但不完整)的解决方案here

它需要一些Apple脚本,因此您需要为每个要支持的邮件应用程序创建不同的脚本,但这似乎是一件容易的事情。

您还需要找到用户的默认邮件应用程序,可以通过构造mailto: URL,然后使用LaunchServices LSGetApplicationForURL()返回默认电子邮件客户端来完成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接