如何创建Apple邮件插件

时间:2012-10-04 05:02:42

标签: objective-c macos cocoa plugins

我将为OS X Mail.app应用程序创建一个邮件插件,以获得一些额外的功能。

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

任何人都可以帮助我,我该如何开始这个项目。 是否有任何初始链接或教程,请提出建议?

2 个答案:

答案 0 :(得分:46)

如上所述,编写Apple Mail插件并不简单,因为它只有一个私有插件API,完全没有文档,可以随任何新版本的Mail.app进行更改。最好的代码示例是GPGMail,它是开源的&仍然有效(已working on Yosemite support)。这是我成功开始的事情(一旦完成就会把它放在github上):

如何构建最小的Apple Mail插件(截至Mavericks& Xcode 6.0.1)

  1. 你需要创建一个OSX" Bundle"项目在XCode
  2. 包装器扩展名为mailbundle(在项目构建设置中的包装下)
  3. 需要将一个包存储在~/Library/Mail/Bundles下(作为构建阶段添加一个复制文件操作,将其作为绝对路径目标,并将构建/文件夹中的* .mailbundle作为要复制的项目)
  4. 对于开发,我在运行方案中将/Applications/Mail.app设置为可执行文件,以便在XCode中运行将构建它,复制包并启动邮件;请注意,此时您将从Mail收到错误,指出您的插件无法启动并被禁用
  5. 您需要在Info.plist中提供SupportedPluginCompatibilityUUIDs的列表,stole it from GPGMail,这些change with new Mail/OSX versions
  6. 使用class-dump从Mail.app的私有API
  7. 生成头文件
  8. 起点是MVMailBundle,你必须继承它,并且有一个registerBundle方法来吸引你
    • 我从一个小的MVMailBundle.h标题中的巨大生成的头文件中提取了该文件,以包含所需的位置(由GPGMail完成)
  9. 创建一个新的类MyMailBundle,继承自NSObject
    • 需要initialize方法
    • 并将其设置为"原则类"在Info.plist中,以便在Mail.app
    • 加载包时运行它
  10. #import <Cocoa/Cocoa.h>
    
    @interface MyMailBundle : NSObject
    
    + (void)initialize;
    @end
    
    1. initialize实施:之前,您可以使用简单的方式,directly inherit作为done in Letterbox,但是,since 64-bit runtimes of Objective-C您必须使用dynamic way as done by GPGMail
      • 使用NSClassFromString动态获取MVMailBundle
      • 来自class_setSuperclass
      • <objc/runtime.h>让您自己的类继承自
      • 然后将registerBundle上的MVMailBundle投标为MVMailBundle.h(需要包含#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
    2. NSLog
      1. 添加一些{{1}}日志记录调用以验证正确的事情,当从XCode内部或系统日志中运行/调试Mail.app时,它们将在XCode的控制台中可见of Console.app
      2. 这应该在Mail中成功运行插件,没有错误!
      3. 接下来的步骤涉及疯狂的事情,例如MethodSwizzlingClassPosing,以修改邮件的行为,其中GPGMail可以是helpful example。 (Haven还没去过那里)
      4. 供参考,以下是一些帮助我的资源:

答案 1 :(得分:4)

没有官方支持的方法来构建这样的工具 - 您需要在没有任何官方支持的情况下开始尝试挂接到Mail.app。

如果你想坚持这种事情,那么你需要了解Mail.app内部的工作方式,这是一堆使用调试器和类转储来检查其他应用程序中的库:

https://github.com/nygard/class-dump

您可能还想要一种方法将代码注入其他应用程序,例如:

https://github.com/rentzsch/mach_inject

每次Apple更新Mail.app时,您都可能需要重做所有内容:)