summaryrefslogtreecommitdiff
path: root/plugins/de.appplant.cordova.plugin.email-composer/src/ios/APPEmailComposer.m
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/de.appplant.cordova.plugin.email-composer/src/ios/APPEmailComposer.m')
-rw-r--r--plugins/de.appplant.cordova.plugin.email-composer/src/ios/APPEmailComposer.m490
1 files changed, 490 insertions, 0 deletions
diff --git a/plugins/de.appplant.cordova.plugin.email-composer/src/ios/APPEmailComposer.m b/plugins/de.appplant.cordova.plugin.email-composer/src/ios/APPEmailComposer.m
new file mode 100644
index 00000000..52bb66d7
--- /dev/null
+++ b/plugins/de.appplant.cordova.plugin.email-composer/src/ios/APPEmailComposer.m
@@ -0,0 +1,490 @@
+/*
+ Copyright 2013-2015 appPlant UG
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "APPEmailComposer.h"
+#import "Cordova/NSData+Base64.h"
+#import "Cordova/CDVAvailability.h"
+#import <MobileCoreServices/MobileCoreServices.h>
+
+#include "TargetConditionals.h"
+
+@interface APPEmailComposer ()
+
+@property (nonatomic, retain) CDVInvokedUrlCommand* command;
+
+@end
+
+@implementation APPEmailComposer
+
+#pragma mark -
+#pragma mark Plugin interface methods
+
+/**
+ * Checks if the mail composer is able to send mails.
+ *
+ * @param callbackId
+ * The ID of the JS function to be called with the result
+ */
+- (void) isAvailable:(CDVInvokedUrlCommand*)command
+{
+ [self.commandDelegate runInBackground:^{
+ bool canSendMail = [MFMailComposeViewController canSendMail];
+ CDVPluginResult* result;
+
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
+ messageAsBool:canSendMail];
+
+ [self.commandDelegate sendPluginResult:result
+ callbackId:command.callbackId];
+ }];
+}
+
+/**
+ * Shows the email composer view with pre-filled data.
+ *
+ * @param properties
+ * The email properties like subject, body, attachments
+ */
+- (void) open:(CDVInvokedUrlCommand*)command
+{
+ _command = command;
+
+ if (TARGET_IPHONE_SIMULATOR && IsAtLeastiOSVersion(@"8.0")) {
+ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Email-Composer Plug-in"
+ message:@"Plug-in cannot run on the iOS8 Simulator.\nPlease downgrade or use a physical device."
+ delegate:nil
+ cancelButtonTitle:@"OK"
+ otherButtonTitles:nil];
+ [alert show];
+ [self execCallback];
+ return;
+ }
+
+ [self.commandDelegate runInBackground:^{
+ NSArray* args = command.arguments;
+ NSDictionary* properties = [args objectAtIndex:0];
+ MFMailComposeViewController* draft;
+
+ draft = [self getDraftWithProperties:properties];
+
+ if (!draft) {
+ [self execCallback];
+ return;
+ }
+
+ [self openDraft:draft];
+ }];
+}
+
+#pragma mark -
+#pragma mark MFMailComposeViewControllerDelegate methods
+
+/**
+ * Delegate will be called after the mail composer did finish an action
+ * to dismiss the view.
+ */
+- (void) mailComposeController:(MFMailComposeViewController*)controller
+ didFinishWithResult:(MFMailComposeResult)result
+ error:(NSError*)error
+{
+ [controller dismissViewControllerAnimated:YES completion:nil];
+
+ [self execCallback];
+}
+
+#pragma mark -
+#pragma mark Plugin core methods
+
+/**
+ * Instantiates an email composer view.
+ *
+ * @param properties
+ * The email properties like subject, body, attachments
+ *
+ * @return
+ * The configured email composer view
+ */
+- (MFMailComposeViewController*) getDraftWithProperties:(NSDictionary*)properties
+{
+ // Falls das Gerät kein Email Interface unterstützt
+ if (![MFMailComposeViewController canSendMail]) {
+ return NULL;
+ }
+
+ BOOL isHTML = [[properties objectForKey:@"isHtml"] boolValue];
+
+ MFMailComposeViewController* draft;
+
+ draft = [[MFMailComposeViewController alloc] init];
+
+ // Subject
+ [self setSubject:[properties objectForKey:@"subject"] ofDraft:draft];
+ // Body (as HTML)
+ [self setBody:[properties objectForKey:@"body"] ofDraft:draft isHTML:isHTML];
+ // Recipients
+ [self setToRecipients:[properties objectForKey:@"to"] ofDraft:draft];
+ // CC Recipients
+ [self setCcRecipients:[properties objectForKey:@"cc"] ofDraft:draft];
+ // BCC Recipients
+ [self setBccRecipients:[properties objectForKey:@"bcc"] ofDraft:draft];
+ // Attachments
+ [self setAttachments:[properties objectForKey:@"attachments"] ofDraft:draft];
+
+ draft.mailComposeDelegate = self;
+
+ return draft;
+}
+
+/**
+ * Displays the email draft.
+ *
+ * @param draft
+ * The email composer view
+ */
+- (void) openDraft:(MFMailComposeViewController*)draft
+{
+ [self.viewController presentViewController:draft
+ animated:YES
+ completion:NULL];
+}
+
+/**
+ * Sets the subject of the email draft.
+ *
+ * @param subject
+ * The subject of the email
+ * @param draft
+ * The email composer view
+ */
+- (void) setSubject:(NSString*)subject
+ ofDraft:(MFMailComposeViewController*)draft
+{
+ [draft setSubject:subject];
+}
+
+/**
+ * Sets the body of the email draft.
+ *
+ * @param body
+ * The body of the email
+ * @param isHTML
+ * Indicates if the body is an HTML encoded string
+ * @param draft
+ * The email composer view
+ */
+- (void) setBody:(NSString*)body ofDraft:(MFMailComposeViewController*)draft
+ isHTML:(BOOL)isHTML
+{
+ [draft setMessageBody:body isHTML:isHTML];
+}
+
+/**
+ * Sets the recipients of the email draft.
+ *
+ * @param recipients
+ * The recipients of the email
+ * @param draft
+ * The email composer view
+ */
+- (void) setToRecipients:(NSArray*)recipients
+ ofDraft:(MFMailComposeViewController*)draft
+{
+ [draft setToRecipients:recipients];
+}
+
+/**
+ * Sets the CC recipients of the email draft.
+ *
+ * @param ccRecipients
+ * The CC recipients of the email
+ * @param draft
+ * The email composer view
+ */
+- (void) setCcRecipients:(NSArray*)ccRecipients
+ ofDraft:(MFMailComposeViewController*)draft
+{
+ [draft setCcRecipients:ccRecipients];
+}
+
+/**
+ * Sets the BCC recipients of the email draft.
+ *
+ * @param bccRecipients
+ * The BCC recipients of the email
+ * @param draft
+ * The email composer view
+ */
+- (void) setBccRecipients:(NSArray*)bccRecipients
+ ofDraft:(MFMailComposeViewController*)draft
+{
+ [draft setBccRecipients:bccRecipients];
+}
+
+/**
+ * Sets the attachments of the email draft.
+ *
+ * @param attachments
+ * The attachments of the email
+ * @param draft
+ * The email composer view
+ */
+- (void) setAttachments:(NSArray*)attatchments
+ ofDraft:(MFMailComposeViewController*)draft
+{
+ if (attatchments)
+ {
+ for (NSString* path in attatchments)
+ {
+ NSData* data = [self getDataForAttachmentPath:path];
+
+ NSString* basename = [self getBasenameFromAttachmentPath:path];
+ NSString* pathExt = [basename pathExtension];
+ NSString* fileName = [basename pathComponents].lastObject;
+ NSString* mimeType = [self getMimeTypeFromFileExtension:pathExt];
+
+ // Couldn't find mimeType, must be some type of binary data
+ if (mimeType == nil) mimeType = @"application/octet-stream";
+
+ [draft addAttachmentData:data mimeType:mimeType fileName:fileName];
+ }
+ }
+}
+
+/**
+ * Returns the data for a given (relative) attachment path.
+ *
+ * @param path
+ * An absolute/relative path or the base64 data
+ *
+ * @return
+ * The data for the attachment
+ */
+- (NSData*) getDataForAttachmentPath:(NSString*)path
+{
+ if ([path hasPrefix:@"file:///"])
+ {
+ return [self dataForAbsolutePath:path];
+ }
+ else if ([path hasPrefix:@"res:"])
+ {
+ return [self dataForResource:path];
+ }
+ else if ([path hasPrefix:@"file://"])
+ {
+ return [self dataForAsset:path];
+ }
+ else if ([path hasPrefix:@"base64:"])
+ {
+ return [self dataFromBase64:path];
+ }
+
+ NSFileManager* fileManager = [NSFileManager defaultManager];
+
+ if (![fileManager fileExistsAtPath:path]){
+ NSLog(@"File not found: %@", path);
+ }
+
+ return [fileManager contentsAtPath:path];
+}
+
+/**
+ * Retrieves the data for an absolute attachment path.
+ *
+ * @param path
+ * An absolute file path
+ *
+ * @return
+ * The data for the attachment
+ */
+- (NSData*) dataForAbsolutePath:(NSString*)path
+{
+ NSFileManager* fileManager = [NSFileManager defaultManager];
+ NSString* absPath;
+
+ absPath = [path stringByReplacingOccurrencesOfString:@"file://"
+ withString:@""];
+
+ if (![fileManager fileExistsAtPath:absPath]){
+ NSLog(@"File not found: %@", absPath);
+ }
+
+ NSData* data = [fileManager contentsAtPath:absPath];
+
+ return data;
+}
+
+/**
+ * Retrieves the data for a resource path.
+ *
+ * @param path
+ * A relative file path
+ *
+ * @return
+ * The data for the attachment
+ */
+- (NSData*) dataForResource:(NSString*)path
+{
+ NSFileManager* fileManager = [NSFileManager defaultManager];
+ NSString* absPath;
+
+ NSBundle* mainBundle = [NSBundle mainBundle];
+ NSString* bundlePath = [[mainBundle bundlePath]
+ stringByAppendingString:@"/"];
+
+ absPath = [path pathComponents].lastObject;
+
+ absPath = [bundlePath stringByAppendingString:absPath];
+
+ if (![fileManager fileExistsAtPath:absPath]){
+ NSLog(@"File not found: %@", absPath);
+ }
+
+ NSData* data = [fileManager contentsAtPath:absPath];
+
+ return data;
+}
+
+/**
+ * Retrieves the data for a asset path.
+ *
+ * @param path
+ * A relative www file path
+ *
+ * @return
+ * The data for the attachment
+ */
+- (NSData*) dataForAsset:(NSString*)path
+{
+ NSFileManager* fileManager = [NSFileManager defaultManager];
+ NSString* absPath;
+
+ NSBundle* mainBundle = [NSBundle mainBundle];
+ NSString* bundlePath = [[mainBundle bundlePath]
+ stringByAppendingString:@"/"];
+
+ absPath = [path stringByReplacingOccurrencesOfString:@"file:/"
+ withString:@"www"];
+
+ absPath = [bundlePath stringByAppendingString:absPath];
+
+ if (![fileManager fileExistsAtPath:absPath]){
+ NSLog(@"File not found: %@", absPath);
+ }
+
+ NSData* data = [fileManager contentsAtPath:absPath];
+
+ return data;
+}
+
+/**
+ * Retrieves the data for a base64 encoded string.
+ *
+ * @param base64String
+ * Base64 encoded string
+ *
+ * @return
+ * The data for the attachment
+ */
+- (NSData*) dataFromBase64:(NSString*)base64String
+{
+ NSUInteger length = [base64String length];
+ NSRegularExpression *regex;
+ NSString *dataString;
+
+ regex = [NSRegularExpression regularExpressionWithPattern:@"^base64:[^/]+.."
+ options:NSRegularExpressionCaseInsensitive
+ error:Nil];
+
+ dataString = [regex stringByReplacingMatchesInString:base64String
+ options:0
+ range:NSMakeRange(0, length)
+ withTemplate:@""];
+
+ NSData* data = [NSData dataFromBase64String:dataString];
+
+ return data;
+}
+
+#pragma mark -
+#pragma mark Plugin helper methods
+
+/**
+ * Retrieves the mime type from the file extension.
+ *
+ * @param extension
+ * The file's extension
+ *
+ * @return
+ * The coresponding MIME type
+ */
+- (NSString*) getMimeTypeFromFileExtension:(NSString*)extension
+{
+ if (!extension) {
+ return nil;
+ }
+
+ // Get the UTI from the file's extension
+ CFStringRef ext = (CFStringRef)CFBridgingRetain(extension);
+ CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL);
+
+ // Converting UTI to a mime type
+ return (NSString*)CFBridgingRelease(UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType));
+}
+
+/**
+ * Retrieves the attachments basename.
+ *
+ * @param path
+ * The file path or bas64 data of the attachment
+ *
+ * @return
+ * The attachments basename
+ */
+- (NSString*) getBasenameFromAttachmentPath:(NSString*)path
+{
+ if ([path hasPrefix:@"base64:"])
+ {
+ NSString* pathWithoutPrefix;
+
+ pathWithoutPrefix = [path stringByReplacingOccurrencesOfString:@"base64:"
+ withString:@""];
+
+ return [pathWithoutPrefix substringToIndex:
+ [pathWithoutPrefix rangeOfString:@"//"].location];
+ }
+
+ return path;
+
+}
+
+/**
+ * Invokes the callback without any parameter.
+ */
+- (void) execCallback
+{
+ CDVPluginResult *result = [CDVPluginResult
+ resultWithStatus:CDVCommandStatus_OK];
+
+ [self.commandDelegate sendPluginResult:result
+ callbackId:_command.callbackId];
+}
+
+@end