如何创建Apple邮件插件 [英] How to create Apple mail plugin

查看:337
本文介绍了如何创建Apple邮件插件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将为OS X Mail.app应用程序创建一个邮件插件,用于一些其他功能。

I'm going to create a mail plugin for the OS X Mail.app application for some additional features.

我不知道从哪里开始,因为没有用于插件的官方文档。

I have no idea where to start as there is no official documentation for plugins.

任何人都可以帮助我,如何开始项目。
有任何初始链接或教程,请建议?

Can anyone please help me, how can I start the project. Is there any initial link or tutorial, please suggest?

推荐答案

如上所述,编写Apple Mail插件并不简单,因为它只有一个私人插件API,这是完全没有记录,可以更改与任何新版本的Mail.app。最好的代码示例是 GPGMail ,它是开放源代码&仍然有效(已在处理Yosemite支持)。这是我成功地做了开始(将放在github一旦完成):

As noted, writing Apple Mail plugins is not straightforward, since it only has a private plugin API, which is entirely undocumented and can change with any new version of Mail.app. The best code example is GPGMail, which is open source & still active (already working on Yosemite support). Here is what I successfully did to get started (will put it up on github once finished):


  1. 您需要在XCode中创建OSXBundle项目

  2. 扩展名为 mailbundle (在项目生成设置中的包装下)

  3. 一个包需要存储在 / Library / Mail / Bundles (作为构建阶段添加一个复制文件操作作为绝对路径目标和* .mailbundle从您的构建/文件夹作为要复制的项目)

  4. 用于开发,我已将 /Applications/Mail.app 设置为在我的运行方案中可执行,以便在XCode中运行将构建它,复制包和启动邮件请注意,此时您将收到来自Mail的错误,表示您的插件无法启动并已停用。

  5. 您需要提供 SupportedPluginCompatibilityUUIDs 在我的从GPGMail偷走,这些使用新的邮件/ OSX版本更改

  6. 使用类转储从Mail.app的私有API生成头文件

  7. 起始点是 MVMailBundle ,你必须继承,并且有一个 registerBundle 方法在

    • 我从一个小的 MVMailBundle.h 头部包含在需要的地方(如GPGMail所做)

  1. you need to create an OSX "Bundle" project in XCode
  2. wrapper extension is mailbundle (under Packaging in the project Build settings)
  3. a bundle needs to be stored under ~/Library/Mail/Bundles (as Build Phase add a Copy Files action with that as absolute path destination and the *.mailbundle from your build/ folder as item to copy)
  4. for development, I have set up /Applications/Mail.app as executable in my run scheme, so that Run in XCode will build it, copy the bundle and start mail; note that at this point you'll get an error from Mail that your plugin cannot be started and was disabled
  5. you need to provide a list of SupportedPluginCompatibilityUUIDs in the Info.plist, I stole it from GPGMail, these change with new Mail/OSX versions
  6. use class-dump to generate the header files from Mail.app's private API
  7. starting point is MVMailBundle, which you have to inherit from and which has a registerBundle method to hook you in
    • I extracted that from the huge generated header file in a small MVMailBundle.h header to include where needed (as done by GPGMail)

  • c $ c> initialize 方法

  • 并在Info.plist中将其设置为Principle class,以便在邮件加载bundle时运行。 app



#import <Cocoa/Cocoa.h>

@interface MyMailBundle : NSObject

+ (void)initialize;
@end




  1. initialize 实现:以前,您可以使用简单的方法和直接继承完成在信箱中,因为64位运行时的Objective-C < a>您必须使用GPGMail执行的动态方式

    • 使用 NSClassFromString 动态获取 MVMailBundle li>
    • class_setSuperclass < objc / runtime.h> 类继承它 c $>
    • 然后调用 registerBundle ,作为 MVMailBundle (需要包含 MVMailBundle.h

  1. initialize implementation: previously, you could use the simple way and directly inherit as done in Letterbox, however, since 64-bit runtimes of Objective-C you have to use the dynamic way as done by GPGMail:
    • using NSClassFromString to dynamically get the MVMailBundle class
    • and class_setSuperclass from <objc/runtime.h> to have your own class inherit from it
    • and then call registerBundle on it casted as MVMailBundle (requires include of MVMailBundle.h)


b $ b

#import <objc/runtime.h>
#import "MVMailBundle.h"
#import "MyMailBundle.h"

@implementation MyMailBundle

+ (void)initialize
{
    NSLog(@"Loading MyMail plugin...");

    // since 64-bit objective-c runtimes, you apparently can't load
    // symbols directly (i.e. through class inheritance) and have to
    // resort to NSClassFromString
    Class mvMailBundleClass = NSClassFromString(@"MVMailBundle");

    // If this class is not available that means Mail.app
    // doesn't allow plugins anymore or has changed the API
    if (!mvMailBundleClass)
        return;

    // dynamically change super class hierarchy
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
    class_setSuperclass([self class], mvMailBundleClass);
#pragma GCC diagnostic pop

    // register our plugin bundle in mail
    [[((MyMailBundle *)self) class] registerBundle];

    NSLog(@"Done registering MyMail plugin.");
}
@end




  1. 添加一些 NSLog 日志调用来验证正确的事情发生,它们将在XCode的控制台中显示,当运行/调试Mail.app从XCode或系统日志的Console.app

  2. 这应该成功运行插件在邮件中没有错误!

  3. 接下来的步骤涉及疯狂的事情,如 MethodSwizzling ClassPosing 修改Mail的行为,其中GPGMail可以是实用示例。 (还没有我自己)

  1. add some NSLog logging calls to verify the right thing is happening, they'll be visible in XCode's console when running/debugging Mail.app from within XCode or alternatively in the system logs of Console.app
  2. This should successfully run the plugin in Mail with no error!
  3. The next steps involve crazy things like MethodSwizzling and ClassPosing to modify Mail's behavior, where GPGMail can be a helpful example. (Haven't been there myself yet)

以下是帮助我的一些资源:

For reference, here are some of the resources that helped me:

  • GPGMail
  • Adam Nash: Getting Ready to Write an Apple Mail.app Plug-in for Mac OS X - some good links, but apparently he never finished the project, so no code
  • James R. Eagan: Demystifying Mail.app Plugins on Leopard - using PyObjC to write a plugin in Python, explains the basic mechansims, very useful
  • Aaron Harnly: Mail Plugin Template - for XCode 2 I think, unfortunately the template (download a zip) doesn't work as template in Xcode anymore, but the code is still useful to look at
  • Aaron Harnly: Letterbox sources - from the same guy, but also from 2007, very outdated; contains a readme from the template, though it doesn't really help if you can't use the template.

这篇关于如何创建Apple邮件插件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆