Nessuna descrizione

APPEmailComposerImpl.m 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. Copyright 2013-2016 appPlant UG
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  11. Unless required by applicable law or agreed to in writing,
  12. software distributed under the License is distributed on an
  13. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. KIND, either express or implied. See the License for the
  15. specific language governing permissions and limitations
  16. under the License.
  17. */
  18. #import "APPEmailComposerImpl.h"
  19. #import <Cordova/CDVAvailability.h>
  20. #ifndef __CORDOVA_4_0_0
  21. #import <Cordova/NSData+Base64.h>
  22. #endif
  23. #import <MessageUI/MFMailComposeViewController.h>
  24. #import <MobileCoreServices/MobileCoreServices.h>
  25. #include "TargetConditionals.h"
  26. /**
  27. * Implements the interface methods of the plugin.
  28. */
  29. @implementation APPEmailComposerImpl
  30. #pragma mark -
  31. #pragma mark Public
  32. /**
  33. * Checks if the mail composer is able to send mails and if an app is available
  34. * to handle the specified scheme.
  35. *
  36. * @param scheme
  37. * An URL scheme, that defaults to 'mailto:
  38. */
  39. - (NSArray*) canSendMail:(NSString*)scheme
  40. {
  41. bool canSendMail = [MFMailComposeViewController canSendMail];
  42. bool withScheme = false;
  43. if (![scheme hasSuffix:@":"]) {
  44. scheme = [scheme stringByAppendingString:@":"];
  45. }
  46. scheme = [[scheme stringByAppendingString:@"test@test.de"]
  47. stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  48. NSURL *url = [[NSURL URLWithString:scheme]
  49. absoluteURL];
  50. withScheme = [[UIApplication sharedApplication]
  51. canOpenURL:url];
  52. if (TARGET_IPHONE_SIMULATOR && [scheme hasPrefix:@"mailto:"]) {
  53. canSendMail = withScheme = true;
  54. }
  55. NSArray* resultArray = [NSArray arrayWithObjects:@(canSendMail),@(withScheme), nil];
  56. return resultArray;
  57. }
  58. /**
  59. * Instantiates an email composer view.
  60. *
  61. * @param properties
  62. * The email properties like subject, body, attachments
  63. * @param delegateTo
  64. * The mail composition view controller’s delegate.
  65. * @return
  66. * The configured email composer view
  67. */
  68. - (MFMailComposeViewController*) mailComposerFromProperties:(NSDictionary*)props
  69. delegateTo:(id)receiver
  70. {
  71. BOOL isHTML = [[props objectForKey:@"isHtml"] boolValue];
  72. MFMailComposeViewController* draft;
  73. draft = [[MFMailComposeViewController alloc] init];
  74. // Subject
  75. [self setSubject:[props objectForKey:@"subject"] ofDraft:draft];
  76. // Body (as HTML)
  77. [self setBody:[props objectForKey:@"body"] ofDraft:draft isHTML:isHTML];
  78. // Recipients
  79. [self setToRecipients:[props objectForKey:@"to"] ofDraft:draft];
  80. // CC Recipients
  81. [self setCcRecipients:[props objectForKey:@"cc"] ofDraft:draft];
  82. // BCC Recipients
  83. [self setBccRecipients:[props objectForKey:@"bcc"] ofDraft:draft];
  84. // Attachments
  85. [self setAttachments:[props objectForKey:@"attachments"] ofDraft:draft];
  86. draft.mailComposeDelegate = receiver;
  87. return draft;
  88. }
  89. /**
  90. * Creates an mailto-url-sheme.
  91. *
  92. * @param properties
  93. * The email properties like subject, body, attachments
  94. * @return
  95. * The configured mailto-sheme
  96. */
  97. - (NSURL*) urlFromProperties:(NSDictionary*)props
  98. {
  99. NSString* mailto = [props objectForKey:@"app"];
  100. NSString* query = @"";
  101. BOOL isHTML = [[props objectForKey:@"isHtml"] boolValue];
  102. NSString* subject = [props objectForKey:@"subject"];
  103. NSString* body = [props objectForKey:@"body"];
  104. NSArray* to = [props objectForKey:@"to"];
  105. NSArray* cc = [props objectForKey:@"cc"];
  106. NSArray* bcc = [props objectForKey:@"bcc"];
  107. NSArray* attachments = [props objectForKey:@"attachments"];
  108. if (![mailto hasSuffix:@":"]) {
  109. mailto = [mailto stringByAppendingString:@":"];
  110. }
  111. mailto = [mailto stringByAppendingString:
  112. [to componentsJoinedByString:@","]];
  113. if (body.length > 0) {
  114. if (isHTML) {
  115. body = [[NSAttributedString alloc] initWithData:[body dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil].string;
  116. }
  117. query = [NSString stringWithFormat: @"%@%@body=%@",
  118. query, query.length > 0? @"&":@"", [body stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
  119. }
  120. if (subject.length > 0) {
  121. query = [NSString stringWithFormat: @"%@%@subject=%@",
  122. query, query.length > 0? @"&":@"", [subject stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
  123. }
  124. if (cc.count > 0) {
  125. query = [NSString stringWithFormat: @"%@%@cc=%@",
  126. query, query.length > 0? @"&":@"", [cc componentsJoinedByString:@","]];
  127. }
  128. if (bcc.count > 0) {
  129. query = [NSString stringWithFormat: @"%@%@bcc=%@",
  130. query, query.length > 0? @"&":@"", [bcc componentsJoinedByString:@","]];
  131. }
  132. if (attachments.count > 0) {
  133. NSLog(@"The 'mailto' URI Scheme (RFC 2368) does not support attachments.");
  134. }
  135. if (query.length > 0) {
  136. query = [@"?" stringByAppendingString:query];
  137. }
  138. mailto = [mailto stringByAppendingString:query];
  139. return [[NSURL URLWithString:mailto] absoluteURL];
  140. }
  141. #pragma mark -
  142. #pragma mark Private
  143. /**
  144. * Sets the subject of the email draft.
  145. *
  146. * @param subject
  147. * The subject of the email.
  148. * @param draft
  149. * The email composer view.
  150. */
  151. - (void) setSubject:(NSString*)subject
  152. ofDraft:(MFMailComposeViewController*)draft
  153. {
  154. [draft setSubject:subject];
  155. }
  156. /**
  157. * Sets the body of the email draft.
  158. *
  159. * @param body
  160. * The body of the email.
  161. * @param isHTML
  162. * Indicates if the body is an HTML encoded string.
  163. * @param draft
  164. * The email composer view.
  165. */
  166. - (void) setBody:(NSString*)body ofDraft:(MFMailComposeViewController*)draft
  167. isHTML:(BOOL)isHTML
  168. {
  169. [draft setMessageBody:body isHTML:isHTML];
  170. }
  171. /**
  172. * Sets the recipients of the email draft.
  173. *
  174. * @param recipients
  175. * The recipients of the email.
  176. * @param draft
  177. * The email composer view.
  178. */
  179. - (void) setToRecipients:(NSArray*)recipients
  180. ofDraft:(MFMailComposeViewController*)draft
  181. {
  182. [draft setToRecipients:recipients];
  183. }
  184. /**
  185. * Sets the CC recipients of the email draft.
  186. *
  187. * @param ccRecipients
  188. * The CC recipients of the email.
  189. * @param draft
  190. * The email composer view.
  191. */
  192. - (void) setCcRecipients:(NSArray*)ccRecipients
  193. ofDraft:(MFMailComposeViewController*)draft
  194. {
  195. [draft setCcRecipients:ccRecipients];
  196. }
  197. /**
  198. * Sets the BCC recipients of the email draft.
  199. *
  200. * @param bccRecipients
  201. * The BCC recipients of the email.
  202. * @param draft
  203. * The email composer view.
  204. */
  205. - (void) setBccRecipients:(NSArray*)bccRecipients
  206. ofDraft:(MFMailComposeViewController*)draft
  207. {
  208. [draft setBccRecipients:bccRecipients];
  209. }
  210. /**
  211. * Sets the attachments of the email draft.
  212. *
  213. * @param attachments
  214. * The attachments of the email.
  215. * @param draft
  216. * The email composer view.
  217. */
  218. - (void) setAttachments:(NSArray*)attatchments
  219. ofDraft:(MFMailComposeViewController*)draft
  220. {
  221. if (attatchments)
  222. {
  223. for (NSString* path in attatchments)
  224. {
  225. NSData* data = [self getDataForAttachmentPath:path];
  226. NSString* basename = [self getBasenameFromAttachmentPath:path];
  227. NSString* pathExt = [basename pathExtension];
  228. NSString* fileName = [basename pathComponents].lastObject;
  229. NSString* mimeType = [self getMimeTypeFromFileExtension:pathExt];
  230. // Couldn't find mimeType, must be some type of binary data
  231. if (mimeType == nil) mimeType = @"application/octet-stream";
  232. [draft addAttachmentData:data mimeType:mimeType fileName:fileName];
  233. }
  234. }
  235. }
  236. /**
  237. * Returns the data for a given (relative) attachment path.
  238. *
  239. * @param path
  240. * An absolute/relative path or the base64 data.
  241. * @return
  242. * The data for the attachment.
  243. */
  244. - (NSData*) getDataForAttachmentPath:(NSString*)path
  245. {
  246. if ([path hasPrefix:@"file:///"])
  247. {
  248. return [self dataForAbsolutePath:path];
  249. }
  250. else if ([path hasPrefix:@"res:"])
  251. {
  252. return [self dataForResource:path];
  253. }
  254. else if ([path hasPrefix:@"file://"])
  255. {
  256. return [self dataForAsset:path];
  257. }
  258. else if ([path hasPrefix:@"base64:"])
  259. {
  260. return [self dataFromBase64:path];
  261. }
  262. NSFileManager* fileManager = [NSFileManager defaultManager];
  263. if (![fileManager fileExistsAtPath:path]){
  264. NSLog(@"File not found: %@", path);
  265. }
  266. return [fileManager contentsAtPath:path];
  267. }
  268. /**
  269. * Retrieves the data for an absolute attachment path.
  270. *
  271. * @param path
  272. * An absolute file path.
  273. * @return
  274. * The data for the attachment.
  275. */
  276. - (NSData*) dataForAbsolutePath:(NSString*)path
  277. {
  278. NSFileManager* fileManager = [NSFileManager defaultManager];
  279. NSString* absPath;
  280. absPath = [path stringByReplacingOccurrencesOfString:@"file://"
  281. withString:@""];
  282. if (![fileManager fileExistsAtPath:absPath]) {
  283. NSLog(@"File not found: %@", absPath);
  284. }
  285. NSData* data = [fileManager contentsAtPath:absPath];
  286. return data;
  287. }
  288. /**
  289. * Retrieves the data for a resource path.
  290. *
  291. * @param path
  292. * A relative file path.
  293. * @return
  294. * The data for the attachment.
  295. */
  296. - (NSData*) dataForResource:(NSString*)path
  297. {
  298. NSString* imgName = [[path pathComponents].lastObject
  299. stringByDeletingPathExtension];
  300. #ifdef __CORDOVA_4_0_0
  301. if ([imgName isEqualToString:@"icon"]) {
  302. imgName = @"AppIcon60x60@3x";
  303. }
  304. #endif
  305. UIImage* img = [UIImage imageNamed:imgName];
  306. if (img == NULL) {
  307. NSLog(@"File not found: %@", path);
  308. }
  309. NSData* data = UIImagePNGRepresentation(img);
  310. return data;
  311. }
  312. /**
  313. * Retrieves the data for a asset path.
  314. *
  315. * @param path
  316. * A relative www file path.
  317. * @return
  318. * The data for the attachment.
  319. */
  320. - (NSData*) dataForAsset:(NSString*)path
  321. {
  322. NSFileManager* fileManager = [NSFileManager defaultManager];
  323. NSString* absPath;
  324. NSBundle* mainBundle = [NSBundle mainBundle];
  325. NSString* bundlePath = [[mainBundle bundlePath]
  326. stringByAppendingString:@"/"];
  327. absPath = [path stringByReplacingOccurrencesOfString:@"file:/"
  328. withString:@"www"];
  329. absPath = [bundlePath stringByAppendingString:absPath];
  330. if (![fileManager fileExistsAtPath:absPath]) {
  331. NSLog(@"File not found: %@", absPath);
  332. }
  333. NSData* data = [fileManager contentsAtPath:absPath];
  334. return data;
  335. }
  336. /**
  337. * Retrieves the data for a base64 encoded string.
  338. *
  339. * @param base64String
  340. * Base64 encoded string.
  341. * @return
  342. * The data for the attachment.
  343. */
  344. - (NSData*) dataFromBase64:(NSString*)base64String
  345. {
  346. NSUInteger length = [base64String length];
  347. NSRegularExpression *regex;
  348. NSString *dataString;
  349. regex = [NSRegularExpression regularExpressionWithPattern:@"^base64:[^/]+.."
  350. options:NSRegularExpressionCaseInsensitive
  351. error:Nil];
  352. dataString = [regex stringByReplacingMatchesInString:base64String
  353. options:0
  354. range:NSMakeRange(0, length)
  355. withTemplate:@""];
  356. #ifndef __CORDOVA_3_8_0
  357. NSData* data = [NSData dataFromBase64String:dataString];
  358. #else
  359. NSData* data = [[NSData alloc] initWithBase64EncodedString:dataString options:0];
  360. #endif
  361. return data;
  362. }
  363. /**
  364. * Retrieves the mime type from the file extension.
  365. *
  366. * @param extension
  367. * The file's extension.
  368. * @return
  369. * The coresponding MIME type.
  370. */
  371. - (NSString*) getMimeTypeFromFileExtension:(NSString*)extension
  372. {
  373. if (!extension) {
  374. return nil;
  375. }
  376. // Get the UTI from the file's extension
  377. CFStringRef ext = (CFStringRef)CFBridgingRetain(extension);
  378. CFStringRef type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL);
  379. ext = NULL;
  380. // Converting UTI to a mime type
  381. return (NSString*)CFBridgingRelease(UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType));
  382. }
  383. /**
  384. * Retrieves the attachments basename.
  385. *
  386. * @param path
  387. * The file path or bas64 data of the attachment.
  388. * @return
  389. * The attachments basename.
  390. */
  391. - (NSString*) getBasenameFromAttachmentPath:(NSString*)path
  392. {
  393. if ([path hasPrefix:@"base64:"])
  394. {
  395. NSString* pathWithoutPrefix;
  396. pathWithoutPrefix = [path stringByReplacingOccurrencesOfString:@"base64:"
  397. withString:@""];
  398. return [pathWithoutPrefix substringToIndex:
  399. [pathWithoutPrefix rangeOfString:@"//"].location];
  400. }
  401. return path;
  402. }
  403. @end