Make your application reply to mailto: links

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

-
For theĀ application ‘Notifier Pro for Gmail’, I wanted to add a ‘compose’ functionality, and also to make it the default mail application when we click on a browser link ‘mailto:’

The first step is to add the following key to your .plist

<key>CFBundleURLTypes</key>
<array>
<dict>
	<key>CFBundleURLName</key>
	<string>Email Address URL</string>
	<key>CFBundleURLSchemes</key>
	<array>
		<string>mailto</string>
	</array>
	<key>LSIsAppleDefaultForScheme</key>
	<true/>
</dict>
</array>

Then tell that your app is responding to the even handler:

NSAppleEventManager* appleEventManager = [NSAppleEventManager sharedAppleEventManager];
    [appleEventManager setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];

with the following function:

- (BOOL)handleGetURLEvent:(NSAppleEventDescriptor*)event withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
 
    NSAppleEventDescriptor* directObjectDescriptor  = [event paramDescriptorForKeyword:keyDirectObject];
    NSString*               urlString               = [directObjectDescriptor stringValue];
    NSURL*                  url                     = [NSURL URLWithString:urlString];
    
    //do what you need with the url
}    

Now we need to tell the OS that our application is the default one that will respond to the ‘mailto’ link.
You can use LSCopyApplicationURLsForURL or LSCopyAllHandlersForURLScheme to get the list of the known application which can respond to the URL link

CFArrayRef bundleList = LSCopyAllHandlersForURLScheme(CFSTR("mailto"));
if (bundleList)
{
    for(CFIndex i=0; i<CFArrayGetCount(bundleList); i++)
    {
        CFStringRef bundle = CFArrayGetValueAtIndex(bundleList, i);
        NSLog(@"%@",(__bridge NSString *)bundle);
    }
}

//or

NSURL *mailtoURL = [NSURL URLWithString:@"mailto:"];
CFArrayRef urlList =  LSCopyApplicationURLsForURL((__bridge CFURLRef)mailtoURL,kLSRolesAll);    
for(CFIndex i=0; i<CFArrayGetCount(urlList); i++)
{
    CFURLRef infoUrl = NULL;
        
    infoUrl = CFArrayGetValueAtIndex(urlList, i);
    if (infoUrl)
    {
        NSURL *u = (__bridge NSURL *)infoUrl;
    }
}

And to set an application as the default one:

NSString *bundleIdentifier = @"com.your.bundleidentifier"; //or get it with NSBundle class
OSStatus status = LSSetDefaultHandlerForURLScheme(CFSTR("mailto"), (__bridge CFStringRef)bundleIdentifier);
NSLog(@"%i",status);

that’s all…. except that I’m running my application in a Sandbox environment, and it returns the error -54 !

After trying to find a solution for this, and on the devforums.apple.com forum, it seems that there is currently no solution, Apple just decided to remove that feature since Yosemite…. It still works on Mavericks.
That of course very disappointing, and even not mentioned in the Apple’s documentation.

However, you still can implement the first part, respond to the URL, and you can use another non-sandboxed app to make your own app as the default one. For the mailto example, your can open the apple Mail.app, go to preferences and change the default mail app… I hope Apple will change that, It really kills some applications main feature and will probably push again many developers to abandon the Mac App Store.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>