29

いくつかの追加機能のために、OSXMail.appアプリケーション用のメールプラグインを作成します。

プラグインの公式ドキュメントがないため、どこから始めればよいかわかりません。

誰かが私を助けてくれますか、どうすればプロジェクトを始めることができますか?最初のリンクやチュートリアルはありますか?提案してください。

4

2 に答える 2

56

前述のように、Apple Mail プラグインの作成は簡単ではありません。プライベート プラグイン API しかなく、完全に文書化されておらず、Mail.app の新しいバージョンで変更される可能性があるためです。最良のコード例はGPGMail です。これはオープン ソースであり、現在もアクティブです (すでにYosemite のサポートに取り組んでいます)。開始するために私が成功したことは次のとおりです(終了したらgithubに載せます):

最小限の Apple Mail プラグインをビルドする方法 (Mavericks & Xcode 6.0.1 以降)

  1. XCodeでOSX「バンドル」プロジェクトを作成する必要があります
  2. ラッパー拡張機能はmailbundle(プロジェクトのビルド設定のパッケージングの下にあります)
  3. バンドルを以下に保存する必要があります~/Library/Mail/Bundles(ビルド フェーズでは、ファイルのコピー アクションを絶対パスの宛先として追加し、build/ フォルダーの *.mailbundle をコピーするアイテムとして追加します)。
  4. /Applications/Mail.app開発のために、Run in XCode がそれをビルドし、バンドルをコピーしてメールを開始するように、実行スキームで実行可能として設定しました。この時点で、メールから、プラグインを開始できず、無効になっているというエラーが表示されることに注意してください。
  5. SupportedPluginCompatibilityUUIDsInfo.plistのリストを提供する必要があります。私は GPGMail から盗みました。これらは新しい Mail/OSX バージョンで変更されます
  6. class-dumpを使用して、Mail.app のプライベート API からヘッダー ファイルを生成します
  7. 開始点はMVMailBundleであり、継承する必要があり、registerBundleフックするメソッドがあります
    • 小さなMVMailBundle.hヘッダーで生成された巨大なヘッダー ファイルからそれを抽出して、必要な場所に含めました (GPGMail によって行われたように)。
  8. MyMailBundleから継承して新しいクラスを作成するNSObject
    • initializeそれには方法が必要です
    • バンドルがMail.appによってロードされたときに実行されるように、Info.plistで「プリンシパルクラス」として設定します
#import <Cocoa/Cocoa.h>

@interface MyMailBundle : NSObject

+ (void)initialize;
@end
  1. initialize実装: 以前は、単純な方法を使用して、 Letterboxで行われたように直接継承できましたが、Objective-C の 64 ビット ランタイム以降、 GPGMail で行われた動的な方法を使用する必要があります。
    • クラスNSClassFromStringを動的に取得するために使用するMVMailBundle
    • 独自のクラスにそれを継承さclass_setSuperclassせる<objc/runtime.h>
    • registerBundleそして、それを次のようにキャストして呼び出しますMVMailBundle( include of が必要です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
  1. 正しいことが起こっていることを確認するためにいくつかのロギング呼び出しを追加NSLogします。それらは、XCode 内から Mail.app を実行/デバッグするときに XCode のコンソールに表示されるか、代わりに Console.app のシステム ログに表示されます。
  2. これにより、メールでプラグインがエラーなしで正常に実行されるはずです!
  3. 次のステップには、MethodSwizzlingClassPosingなどのクレイジーなものが含まれており、メールの動作を変更します。GPGMail が役立つ例です。(自分はまだ行ったことがない)

参考までに、私を助けてくれたリソースの一部を以下に示します。

于 2014-09-29T06:24:28.950 に答える
4

このようなツールを作成するための公式にサポートされている方法はありません。公式のサポートなしで Mail.app への接続を試みる必要があります。

この種のことに固執したい場合は、Mail.app の内部がどのように機能するかを理解する必要があります。これは、デバッガーとクラス ダンプを使用して他のアプリのライブラリを検査することです。

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

おそらく、他のアプリケーションにコードを挿入する方法も必要になるでしょう。たとえば、次のようになります。

https://github.com/rentzsch/mach_inject

Apple が Mail.app を更新するたびに、すべてをやり直す必要がある可能性があります :)

于 2012-10-04T07:49:20.743 に答える