From 1924d12671fd2c2890d8f96c067f702d9800c971 Mon Sep 17 00:00:00 2001 From: chirag04 Date: Sun, 30 Jun 2019 20:41:12 -0400 Subject: [PATCH 01/24] 4.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index df4c0f3..adb9a21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "3.0.7", + "version": "4.0.0", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 6ce0769..947926f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "3.0.7", + "version": "4.0.0", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From d20120e70203a83cb863b41222990e97acec66ed Mon Sep 17 00:00:00 2001 From: Charly BERTHET Date: Mon, 11 Nov 2019 00:01:38 +0100 Subject: [PATCH 02/24] Handle errors related to attached file on iOS (#141) --- RNMail/RNMail.m | 91 +++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 49 deletions(-) diff --git a/RNMail/RNMail.m b/RNMail/RNMail.m index 7e97c42..0d0c50c 100644 --- a/RNMail/RNMail.m +++ b/RNMail/RNMail.m @@ -42,7 +42,7 @@ RCT_EXPORT_METHOD(mail:(NSDictionary *)options [mail setSubject:subject]; } - bool *isHTML = NO; + BOOL isHTML = NO; if (options[@"isHTML"]){ isHTML = [options[@"isHTML"] boolValue]; @@ -72,7 +72,13 @@ RCT_EXPORT_METHOD(mail:(NSDictionary *)options NSString *attachmentPath = [RCTConvert NSString:options[@"attachment"][@"path"]]; NSString *attachmentType = [RCTConvert NSString:options[@"attachment"][@"type"]]; NSString *attachmentName = [RCTConvert NSString:options[@"attachment"][@"name"]]; - + + NSFileManager *fileManager = [NSFileManager defaultManager]; + if (![fileManager fileExistsAtPath:attachmentPath]){ + callback(@[[NSString stringWithFormat: @"attachment file with path '%@' does not exist", attachmentPath]]); + return; + } + // Set default filename if not specificed if (!attachmentName) { attachmentName = [[attachmentPath lastPathComponent] stringByDeletingPathExtension]; @@ -83,53 +89,40 @@ RCT_EXPORT_METHOD(mail:(NSDictionary *)options // Determine the MIME type NSString *mimeType; - - /* - * Add additional mime types and PR if necessary. Find the list - * of supported formats at http://www.iana.org/assignments/media-types/media-types.xhtml - */ - if ([attachmentType isEqualToString:@"jpg"]) { - mimeType = @"image/jpeg"; - } else if ([attachmentType isEqualToString:@"png"]) { - mimeType = @"image/png"; - } else if ([attachmentType isEqualToString:@"doc"]) { - mimeType = @"application/msword"; - } else if ([attachmentType isEqualToString:@"docx"]) { - mimeType = @"application/vnd.openxmlformats-officedocument.wordprocessingml.document"; - } else if ([attachmentType isEqualToString:@"ppt"]) { - mimeType = @"application/vnd.ms-powerpoint"; - } else if ([attachmentType isEqualToString:@"pptx"]) { - mimeType = @"application/vnd.openxmlformats-officedocument.presentationml.presentation"; - } else if ([attachmentType isEqualToString:@"html"]) { - mimeType = @"text/html"; - } else if ([attachmentType isEqualToString:@"csv"]) { - mimeType = @"text/csv"; - } else if ([attachmentType isEqualToString:@"pdf"]) { - mimeType = @"application/pdf"; - } else if ([attachmentType isEqualToString:@"vcard"]) { - mimeType = @"text/vcard"; - } else if ([attachmentType isEqualToString:@"json"]) { - mimeType = @"application/json"; - } else if ([attachmentType isEqualToString:@"zip"]) { - mimeType = @"application/zip"; - } else if ([attachmentType isEqualToString:@"text"]) { - mimeType = @"text/*"; - } else if ([attachmentType isEqualToString:@"mp3"]) { - mimeType = @"audio/mpeg"; - } else if ([attachmentType isEqualToString:@"wav"]) { - mimeType = @"audio/wav"; - } else if ([attachmentType isEqualToString:@"aiff"]) { - mimeType = @"audio/aiff"; - } else if ([attachmentType isEqualToString:@"flac"]) { - mimeType = @"audio/flac"; - } else if ([attachmentType isEqualToString:@"ogg"]) { - mimeType = @"audio/ogg"; - } else if ([attachmentType isEqualToString:@"xls"]) { - mimeType = @"application/vnd.ms-excel"; - } else if ([attachmentType isEqualToString:@"ics"]) { - mimeType = @"text/calendar"; - } else if ([attachmentType isEqualToString:@"xlsx"]) { - mimeType = @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + if (attachmentType) { + /* + * Add additional mime types and PR if necessary. Find the list + * of supported formats at http://www.iana.org/assignments/media-types/media-types.xhtml + */ + NSDictionary *supportedMimeTypes = @{ + @"jpg" : @"image/jpeg", + @"png" : @"image/png", + @"doc" : @"application/msword", + @"docx" : @"application/vnd.openxmlformats-officedocument.wordprocessingml.document", + @"ppt" : @"application/vnd.ms-powerpoint", + @"pptx" : @"application/vnd.openxmlformats-officedocument.presentationml.presentation", + @"html" : @"text/html", + @"csv" : @"text/csv", + @"pdf" : @"application/pdf", + @"vcard" : @"text/vcard", + @"json" : @"application/json", + @"zip" : @"application/zip", + @"text" : @"text/*", + @"mp3" : @"audio/mpeg", + @"wav" : @"audio/wav", + @"aiff" : @"audio/aiff", + @"flac" : @"audio/flac", + @"ogg" : @"audio/ogg", + @"xls" : @"application/vnd.ms-excel", + @"ics" : @"text/calendar", + @"xlsx" : @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + }; + if([supportedMimeTypes objectForKey:attachmentType]) { + mimeType = [supportedMimeTypes objectForKey:attachmentType]; + } else { + callback(@[[NSString stringWithFormat: @"Mime type '%@' for attachment is not handled", attachmentType]]); + return; + } } // Add attachment From 3677dea9ad6bdf6e5e3807ed484c16292b29b8f3 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Sun, 10 Nov 2019 18:02:57 -0500 Subject: [PATCH 03/24] 4.1.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index adb9a21..2260e7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "4.0.0", + "version": "4.1.0", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 947926f..4327bda 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "4.0.0", + "version": "4.1.0", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From d31f9887bfe488d48d8000b410f887b5c66041ad Mon Sep 17 00:00:00 2001 From: David Angulo Date: Mon, 16 Mar 2020 21:28:44 +0800 Subject: [PATCH 04/24] Add jpeg extension mime type (#148) --- RNMail/RNMail.m | 1 + 1 file changed, 1 insertion(+) diff --git a/RNMail/RNMail.m b/RNMail/RNMail.m index 0d0c50c..3b9af59 100644 --- a/RNMail/RNMail.m +++ b/RNMail/RNMail.m @@ -95,6 +95,7 @@ RCT_EXPORT_METHOD(mail:(NSDictionary *)options * of supported formats at http://www.iana.org/assignments/media-types/media-types.xhtml */ NSDictionary *supportedMimeTypes = @{ + @"jpeg" : @"image/jpeg", @"jpg" : @"image/jpeg", @"png" : @"image/png", @"doc" : @"application/msword", From 268b16f65516afec0b5ba47fda21658224d065f4 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 21 May 2020 15:18:09 +0300 Subject: [PATCH 05/24] Support multiple attachments and custom mimeType (#150) * Support multiple attachments and custom mimeType * Fix typo * Add mimeType to README --- README.md | 5 +- RNMail/RNMail.m | 143 +++++++++--------- .../java/com/chirag/RNMail/RNMailModule.java | 24 +-- 3 files changed, 93 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index 3bf1f4c..9d384a3 100644 --- a/README.md +++ b/README.md @@ -125,11 +125,12 @@ export default class App extends Component { bccRecipients: ['supportBCC@example.com'], body: 'A Bold Body', isHTML: true, - attachment: { + attachments: [{ path: '', // The absolute path of the file from which to read data. type: '', // Mime Type: jpg, png, doc, ppt, html, pdf, csv + // mimeType - use only if you want to use custom type name: '', // Optional: Custom filename for attachment - } + }] }, (error, event) => { Alert.alert( error, diff --git a/RNMail/RNMail.m b/RNMail/RNMail.m index 3b9af59..3224d5b 100644 --- a/RNMail/RNMail.m +++ b/RNMail/RNMail.m @@ -36,102 +36,109 @@ RCT_EXPORT_METHOD(mail:(NSDictionary *)options MFMailComposeViewController *mail = [[MFMailComposeViewController alloc] init]; mail.mailComposeDelegate = self; _callbacks[RCTKeyForInstance(mail)] = callback; - + if (options[@"subject"]){ NSString *subject = [RCTConvert NSString:options[@"subject"]]; [mail setSubject:subject]; } - + BOOL isHTML = NO; - + if (options[@"isHTML"]){ isHTML = [options[@"isHTML"] boolValue]; } - + if (options[@"body"]){ NSString *body = [RCTConvert NSString:options[@"body"]]; [mail setMessageBody:body isHTML:isHTML]; } - + if (options[@"recipients"]){ NSArray *recipients = [RCTConvert NSArray:options[@"recipients"]]; [mail setToRecipients:recipients]; } - + if (options[@"ccRecipients"]){ NSArray *ccRecipients = [RCTConvert NSArray:options[@"ccRecipients"]]; [mail setCcRecipients:ccRecipients]; } - + if (options[@"bccRecipients"]){ NSArray *bccRecipients = [RCTConvert NSArray:options[@"bccRecipients"]]; [mail setBccRecipients:bccRecipients]; } - - if (options[@"attachment"] && options[@"attachment"][@"path"] && options[@"attachment"][@"type"]){ - NSString *attachmentPath = [RCTConvert NSString:options[@"attachment"][@"path"]]; - NSString *attachmentType = [RCTConvert NSString:options[@"attachment"][@"type"]]; - NSString *attachmentName = [RCTConvert NSString:options[@"attachment"][@"name"]]; - - NSFileManager *fileManager = [NSFileManager defaultManager]; - if (![fileManager fileExistsAtPath:attachmentPath]){ - callback(@[[NSString stringWithFormat: @"attachment file with path '%@' does not exist", attachmentPath]]); - return; - } - - // Set default filename if not specificed - if (!attachmentName) { - attachmentName = [[attachmentPath lastPathComponent] stringByDeletingPathExtension]; - } - - // Get the resource path and read the file using NSData - NSData *fileData = [NSData dataWithContentsOfFile:attachmentPath]; - - // Determine the MIME type - NSString *mimeType; - if (attachmentType) { - /* - * Add additional mime types and PR if necessary. Find the list - * of supported formats at http://www.iana.org/assignments/media-types/media-types.xhtml - */ - NSDictionary *supportedMimeTypes = @{ - @"jpeg" : @"image/jpeg", - @"jpg" : @"image/jpeg", - @"png" : @"image/png", - @"doc" : @"application/msword", - @"docx" : @"application/vnd.openxmlformats-officedocument.wordprocessingml.document", - @"ppt" : @"application/vnd.ms-powerpoint", - @"pptx" : @"application/vnd.openxmlformats-officedocument.presentationml.presentation", - @"html" : @"text/html", - @"csv" : @"text/csv", - @"pdf" : @"application/pdf", - @"vcard" : @"text/vcard", - @"json" : @"application/json", - @"zip" : @"application/zip", - @"text" : @"text/*", - @"mp3" : @"audio/mpeg", - @"wav" : @"audio/wav", - @"aiff" : @"audio/aiff", - @"flac" : @"audio/flac", - @"ogg" : @"audio/ogg", - @"xls" : @"application/vnd.ms-excel", - @"ics" : @"text/calendar", - @"xlsx" : @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" - }; - if([supportedMimeTypes objectForKey:attachmentType]) { - mimeType = [supportedMimeTypes objectForKey:attachmentType]; - } else { - callback(@[[NSString stringWithFormat: @"Mime type '%@' for attachment is not handled", attachmentType]]); - return; + if (options[@"attachments"]) { + NSArray *attachments = [RCTConvert NSArray:options[@"attachments"]]; + for (NSDictionary *attachment in attachments) { + if (attachment[@"path"] && (attachment[@"type"] || attachment[@"mimeType"])) { + NSString *attachmentPath = [RCTConvert NSString:attachment[@"path"]]; + NSString *attachmentType = [RCTConvert NSString:attachment[@"type"]]; + NSString *attachmentName = [RCTConvert NSString:attachment[@"name"]]; + NSString *attachmentMimeType = [RCTConvert NSString:attachment[@"mimeType"]]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + if (![fileManager fileExistsAtPath:attachmentPath]){ + callback(@[[NSString stringWithFormat: @"attachment file with path '%@' does not exist", attachmentPath]]); + return; + } + + // Set default filename if not specificed + if (!attachmentName) { + attachmentName = [[attachmentPath lastPathComponent] stringByDeletingPathExtension]; + } + + // Get the resource path and read the file using NSData + NSData *fileData = [NSData dataWithContentsOfFile:attachmentPath]; + + // Determine the MIME type + NSString *mimeType; + if (attachmentType) { + /* + * Add additional mime types and PR if necessary. Find the list + * of supported formats at http://www.iana.org/assignments/media-types/media-types.xhtml + */ + NSDictionary *supportedMimeTypes = @{ + @"jpeg" : @"image/jpeg", + @"jpg" : @"image/jpeg", + @"png" : @"image/png", + @"doc" : @"application/msword", + @"docx" : @"application/vnd.openxmlformats-officedocument.wordprocessingml.document", + @"ppt" : @"application/vnd.ms-powerpoint", + @"pptx" : @"application/vnd.openxmlformats-officedocument.presentationml.presentation", + @"html" : @"text/html", + @"csv" : @"text/csv", + @"pdf" : @"application/pdf", + @"vcard" : @"text/vcard", + @"json" : @"application/json", + @"zip" : @"application/zip", + @"text" : @"text/*", + @"mp3" : @"audio/mpeg", + @"wav" : @"audio/wav", + @"aiff" : @"audio/aiff", + @"flac" : @"audio/flac", + @"ogg" : @"audio/ogg", + @"xls" : @"application/vnd.ms-excel", + @"ics" : @"text/calendar", + @"xlsx" : @"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + }; + if([supportedMimeTypes objectForKey:attachmentType]) { + mimeType = [supportedMimeTypes objectForKey:attachmentType]; + } else { + callback(@[[NSString stringWithFormat: @"Mime type '%@' for attachment is not handled", attachmentType]]); + return; + } + } else if (attachmentMimeType) { + mimeType = attachmentMimeType; + } + + // Add attachment + [mail addAttachmentData:fileData mimeType:mimeType fileName:attachmentName]; } } - - // Add attachment - [mail addAttachmentData:fileData mimeType:mimeType fileName:attachmentName]; } - + UIViewController *root = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; - + while (root.presentedViewController) { root = root.presentedViewController; } diff --git a/android/src/main/java/com/chirag/RNMail/RNMailModule.java b/android/src/main/java/com/chirag/RNMail/RNMailModule.java index 658ce6a..77763f3 100644 --- a/android/src/main/java/com/chirag/RNMail/RNMailModule.java +++ b/android/src/main/java/com/chirag/RNMail/RNMailModule.java @@ -84,15 +84,21 @@ public class RNMailModule extends ReactContextBaseJavaModule { i.putExtra(Intent.EXTRA_BCC, readableArrayToStringArray(bccRecipients)); } - if (options.hasKey("attachment") && !options.isNull("attachment")) { - ReadableMap attachment = options.getMap("attachment"); - if (attachment.hasKey("path") && !attachment.isNull("path")) { - String path = attachment.getString("path"); - File file = new File(path); - Uri p = Uri.fromFile(file); - i.putExtra(Intent.EXTRA_STREAM, p); - } - } + if (options.hasKey("attachments") && !options.isNull("attachments")) { + ReadableArray r = options.getArray("attachments"); + int length = r.size(); + ArrayList uris = new ArrayList(); + for (int keyIndex = 0; keyIndex < length; keyIndex++) { + ReadableMap clip = r.getMap(keyIndex); + if (clip.hasKey("path") && !clip.isNull("path")){ + String path = clip.getString("path"); + File file = new File(path); + Uri u = Uri.fromFile(file); + uris.add(u); + } + } + i.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); + } PackageManager manager = reactContext.getPackageManager(); List list = manager.queryIntentActivities(i, 0); From 3c16238a1f02af4c2a888746d3ab3cd0e3affaca Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Mon, 25 May 2020 11:37:24 -0400 Subject: [PATCH 06/24] 5.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2260e7a..cea0017 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "4.1.0", + "version": "5.0.0", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 4327bda..be852f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "4.1.0", + "version": "5.0.0", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From f9c89a69d0d575b84c0f1a22bd0d7c3e13e45927 Mon Sep 17 00:00:00 2001 From: Dominik Tenelsen Date: Tue, 26 May 2020 17:00:46 +0200 Subject: [PATCH 07/24] Fix ArrayList Import (#152) --- android/src/main/java/com/chirag/RNMail/RNMailModule.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/main/java/com/chirag/RNMail/RNMailModule.java b/android/src/main/java/com/chirag/RNMail/RNMailModule.java index 77763f3..398ba03 100644 --- a/android/src/main/java/com/chirag/RNMail/RNMailModule.java +++ b/android/src/main/java/com/chirag/RNMail/RNMailModule.java @@ -15,6 +15,7 @@ import com.facebook.react.bridge.Callback; import java.util.List; import java.io.File; +import java.util.ArrayList; /** * NativeModule that allows JS to open emails sending apps chooser. From 3f92682f113c5fc363dd9cc27e9688bd6afadfe4 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Tue, 26 May 2020 11:01:26 -0400 Subject: [PATCH 08/24] 5.0.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index cea0017..b229ef8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "5.0.0", + "version": "5.0.1", "lockfileVersion": 1 } diff --git a/package.json b/package.json index be852f6..d572bab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "5.0.0", + "version": "5.0.1", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From 5a28255173dde19ad36169f5156a10648cea177c Mon Sep 17 00:00:00 2001 From: Dominik Tenelsen Date: Tue, 25 Aug 2020 14:29:25 +0200 Subject: [PATCH 09/24] Workaround for Android Multiple Attachments bug (#158) this workaround allows to send one attachment in the current v5. --- android/src/main/java/com/chirag/RNMail/RNMailModule.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/chirag/RNMail/RNMailModule.java b/android/src/main/java/com/chirag/RNMail/RNMailModule.java index 398ba03..f32665f 100644 --- a/android/src/main/java/com/chirag/RNMail/RNMailModule.java +++ b/android/src/main/java/com/chirag/RNMail/RNMailModule.java @@ -98,7 +98,12 @@ public class RNMailModule extends ReactContextBaseJavaModule { uris.add(u); } } - i.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); + + if (uris.size() == 1) { + i.putExtra(Intent.EXTRA_STREAM, uris.get(0)); + } else { + i.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); + } } PackageManager manager = reactContext.getPackageManager(); From 8c289a6d900372aadd930d9717a9e48f7271062a Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Tue, 25 Aug 2020 08:30:00 -0400 Subject: [PATCH 10/24] 5.0.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b229ef8..d21de60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "5.0.1", + "version": "5.0.2", "lockfileVersion": 1 } diff --git a/package.json b/package.json index d572bab..321281c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "5.0.1", + "version": "5.0.2", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From d1474c3002b08d925b2d5ef059d4fbabeea6bc85 Mon Sep 17 00:00:00 2001 From: Dominik Tenelsen Date: Tue, 25 Aug 2020 14:34:20 +0200 Subject: [PATCH 11/24] Add prop to change the title of IntentChooser on Android (#159) * Allow custom IntentChooser Title on Android * customChooserTitle prop added to example * Add default value to comment in example --- README.md | 1 + android/src/main/java/com/chirag/RNMail/RNMailModule.java | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d384a3..3e60978 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ export default class App extends Component { ccRecipients: ['supportCC@example.com'], bccRecipients: ['supportBCC@example.com'], body: 'A Bold Body', + customChooserTitle: "This is my new title", // Android only (defaults to "Send Mail") isHTML: true, attachments: [{ path: '', // The absolute path of the file from which to read data. diff --git a/android/src/main/java/com/chirag/RNMail/RNMailModule.java b/android/src/main/java/com/chirag/RNMail/RNMailModule.java index f32665f..bcd00c4 100644 --- a/android/src/main/java/com/chirag/RNMail/RNMailModule.java +++ b/android/src/main/java/com/chirag/RNMail/RNMailModule.java @@ -122,7 +122,13 @@ public class RNMailModule extends ReactContextBaseJavaModule { callback.invoke("error"); } } else { - Intent chooser = Intent.createChooser(i, "Send Mail"); + String chooserTitle = "Send Mail"; + + if (options.hasKey("customChooserTitle") && !options.isNull("customChooserTitle")) { + chooserTitle = options.getString("customChooserTitle"); + } + + Intent chooser = Intent.createChooser(i, chooserTitle); chooser.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { From d8b0b08ef3c752a91ec00ef59ab11036bd6142e4 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Tue, 25 Aug 2020 08:35:11 -0400 Subject: [PATCH 12/24] 5.1.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index d21de60..59f6cc5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "5.0.2", + "version": "5.1.0", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 321281c..d2f265b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "5.0.2", + "version": "5.1.0", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From 940b80db3ea2e66a64b99a9dc40c39ddb466bd36 Mon Sep 17 00:00:00 2001 From: Geraint White Date: Thu, 3 Sep 2020 14:18:07 +0100 Subject: [PATCH 13/24] Support multiple attachments on Android (#161) --- android/src/main/AndroidManifest.xml | 15 ++++- .../com/chirag/RNMail/RNMailFileProvider.java | 7 +++ .../java/com/chirag/RNMail/RNMailModule.java | 59 +++++++++++-------- android/src/main/res/xml/provider_paths.xml | 6 ++ 4 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 android/src/main/java/com/chirag/RNMail/RNMailFileProvider.java create mode 100644 android/src/main/res/xml/provider_paths.xml diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 914eec5..1c61a40 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,4 +1,15 @@ + package="com.chirag.RNMail"> - \ No newline at end of file + + + + + + diff --git a/android/src/main/java/com/chirag/RNMail/RNMailFileProvider.java b/android/src/main/java/com/chirag/RNMail/RNMailFileProvider.java new file mode 100644 index 0000000..45cf23e --- /dev/null +++ b/android/src/main/java/com/chirag/RNMail/RNMailFileProvider.java @@ -0,0 +1,7 @@ +package com.chirag.RNMail; + +import androidx.core.content.FileProvider; + +public class RNMailFileProvider extends FileProvider { + +} diff --git a/android/src/main/java/com/chirag/RNMail/RNMailModule.java b/android/src/main/java/com/chirag/RNMail/RNMailModule.java index bcd00c4..8460848 100644 --- a/android/src/main/java/com/chirag/RNMail/RNMailModule.java +++ b/android/src/main/java/com/chirag/RNMail/RNMailModule.java @@ -5,6 +5,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.text.Html; +import androidx.core.content.FileProvider; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -15,6 +16,7 @@ import com.facebook.react.bridge.Callback; import java.util.List; import java.io.File; +import java.net.URI; import java.util.ArrayList; /** @@ -54,8 +56,9 @@ public class RNMailModule extends ReactContextBaseJavaModule { @ReactMethod public void mail(ReadableMap options, Callback callback) { - Intent i = new Intent(Intent.ACTION_SENDTO); - i.setData(Uri.parse("mailto:")); + Intent i = new Intent(Intent.ACTION_SEND_MULTIPLE); + Intent selectorIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:")); + i.setSelector(selectorIntent); if (options.hasKey("subject") && !options.isNull("subject")) { i.putExtra(Intent.EXTRA_SUBJECT, options.getString("subject")); @@ -86,25 +89,33 @@ public class RNMailModule extends ReactContextBaseJavaModule { } if (options.hasKey("attachments") && !options.isNull("attachments")) { - ReadableArray r = options.getArray("attachments"); - int length = r.size(); - ArrayList uris = new ArrayList(); - for (int keyIndex = 0; keyIndex < length; keyIndex++) { - ReadableMap clip = r.getMap(keyIndex); - if (clip.hasKey("path") && !clip.isNull("path")){ - String path = clip.getString("path"); - File file = new File(path); - Uri u = Uri.fromFile(file); - uris.add(u); - } - } - - if (uris.size() == 1) { - i.putExtra(Intent.EXTRA_STREAM, uris.get(0)); - } else { - i.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); - } - } + ReadableArray r = options.getArray("attachments"); + int length = r.size(); + + String provider = reactContext.getApplicationContext().getPackageName() + ".rnmail.provider"; + List resolvedIntentActivities = reactContext.getPackageManager().queryIntentActivities(i, + PackageManager.MATCH_DEFAULT_ONLY); + + ArrayList uris = new ArrayList(); + for (int keyIndex = 0; keyIndex < length; keyIndex++) { + ReadableMap clip = r.getMap(keyIndex); + if (clip.hasKey("path") && !clip.isNull("path")){ + String path = clip.getString("path"); + File file = new File(path); + Uri uri = FileProvider.getUriForFile(reactContext, provider, file); + uris.add(uri); + + for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) { + String packageName = resolvedIntentInfo.activityInfo.packageName; + reactContext.grantUriPermission(packageName, uri, + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + } + } + + i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + i.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); + } PackageManager manager = reactContext.getPackageManager(); List list = manager.queryIntentActivities(i, 0); @@ -123,11 +134,11 @@ public class RNMailModule extends ReactContextBaseJavaModule { } } else { String chooserTitle = "Send Mail"; - + if (options.hasKey("customChooserTitle") && !options.isNull("customChooserTitle")) { chooserTitle = options.getString("customChooserTitle"); - } - + } + Intent chooser = Intent.createChooser(i, chooserTitle); chooser.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); diff --git a/android/src/main/res/xml/provider_paths.xml b/android/src/main/res/xml/provider_paths.xml new file mode 100644 index 0000000..97384e1 --- /dev/null +++ b/android/src/main/res/xml/provider_paths.xml @@ -0,0 +1,6 @@ + + + + + + From 627c06b0c1e8f4a03bad3586a8d14406cfe1c771 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Thu, 3 Sep 2020 09:18:30 -0400 Subject: [PATCH 14/24] 5.2.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 59f6cc5..7d41824 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "5.1.0", + "version": "5.2.0", "lockfileVersion": 1 } diff --git a/package.json b/package.json index d2f265b..689f70e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "5.1.0", + "version": "5.2.0", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From 249134b0b6720427142d4c07e84bf0a5299e653e Mon Sep 17 00:00:00 2001 From: Ivan Sorokin Date: Thu, 1 Oct 2020 20:37:50 +0200 Subject: [PATCH 15/24] fix: autolinking when using Xcode 12 (#163) --- react-native-mail.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-native-mail.podspec b/react-native-mail.podspec index e31b682..41d4683 100644 --- a/react-native-mail.podspec +++ b/react-native-mail.podspec @@ -13,6 +13,6 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/chirag04/react-native-mail", :tag => "v#{s.version}" } s.source_files = 'RNMail/*.{h,m}' - s.dependency 'React' + s.dependency 'React-Core' end From 2a7b4a07b1b4b01224859ce0e2a1014d40d5aa84 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Mon, 5 Oct 2020 13:38:20 -0400 Subject: [PATCH 16/24] 6.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7d41824..3a667c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "5.2.0", + "version": "6.0.0", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 689f70e..2962fe5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "5.2.0", + "version": "6.0.0", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From a9fc86827324ff3343bed9791b6590da9e9b4ab7 Mon Sep 17 00:00:00 2001 From: jiggag Date: Tue, 9 Mar 2021 00:00:48 +0900 Subject: [PATCH 17/24] Create index.d.ts (#171) --- index.d.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 index.d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..b954b24 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,22 @@ +export namespace Mailer { + function mail(options: { + subject?: string; + recipients?: string[]; + ccRecipients?: string[]; + bccRecipients?: string[]; + body?: string; + customChooserTitle?: string; + isHTML?: boolean; + attachments: { + path: string; + type?: string; + mimeType?: string; + name?: string; + }[] + }, callback: ( + error: string, + event?: string + ) => void): void; +} + +export default Mailer; From da8611761d04597ead6ef2b10d0b27198f667cf9 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Thu, 18 Mar 2021 16:38:24 -0400 Subject: [PATCH 18/24] 6.0.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3a667c9..052efe8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "6.0.0", + "version": "6.0.1", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 2962fe5..8f79fce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "6.0.0", + "version": "6.0.1", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From 066baae83973ba21d517f8f26895ce64f25e5b09 Mon Sep 17 00:00:00 2001 From: jihokim2 Date: Fri, 19 Mar 2021 23:07:47 +0900 Subject: [PATCH 19/24] Update index.d.ts (#173) --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index b954b24..90606f1 100644 --- a/index.d.ts +++ b/index.d.ts @@ -7,7 +7,7 @@ export namespace Mailer { body?: string; customChooserTitle?: string; isHTML?: boolean; - attachments: { + attachments?: { path: string; type?: string; mimeType?: string; From 18689d34c733cb2c03150d58cbf63e468d150364 Mon Sep 17 00:00:00 2001 From: Chirag Jain Date: Fri, 19 Mar 2021 10:08:19 -0400 Subject: [PATCH 20/24] 6.0.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 052efe8..003d040 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "6.0.1", + "version": "6.0.2", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 8f79fce..79a1e5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "6.0.1", + "version": "6.0.2", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From 716f28e66921bcd1558c43956a7a12055d1a04c5 Mon Sep 17 00:00:00 2001 From: Robert Gardner Date: Tue, 23 Mar 2021 07:37:06 -0700 Subject: [PATCH 21/24] Support URI for attachment location. (#174) * Support URI for attachment location. * Add example path & uri to README comments. --- README.md | 16 ++++++---- RNMail/RNMail.m | 30 +++++++++++++------ .../java/com/chirag/RNMail/RNMailModule.java | 23 +++++++++----- index.d.ts | 5 ++-- package.json | 2 +- 5 files changed, 51 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 3e60978..819cc10 100644 --- a/README.md +++ b/README.md @@ -124,13 +124,19 @@ export default class App extends Component { ccRecipients: ['supportCC@example.com'], bccRecipients: ['supportBCC@example.com'], body: 'A Bold Body', - customChooserTitle: "This is my new title", // Android only (defaults to "Send Mail") + customChooserTitle: 'This is my new title', // Android only (defaults to "Send Mail") isHTML: true, attachments: [{ - path: '', // The absolute path of the file from which to read data. - type: '', // Mime Type: jpg, png, doc, ppt, html, pdf, csv - // mimeType - use only if you want to use custom type - name: '', // Optional: Custom filename for attachment + // Specify either `path` or `uri` to indicate where to find the file data. + // The API used to create or locate the file will usually indicate which it returns. + // An absolute path will look like: /cacheDir/photos/some image.jpg + // A URI starts with a protocol and looks like: content://appname/cacheDir/photos/some%20image.jpg + path: '', // The absolute path of the file from which to read data. + uri: '', // The uri of the file from which to read the data. + // Specify either `type` or `mimeType` to indicate the type of data. + type: '', // Mime Type: jpg, png, doc, ppt, html, pdf, csv + mimeType: '', // - use only if you want to use custom type + name: '', // Optional: Custom filename for attachment }] }, (error, event) => { Alert.alert( diff --git a/RNMail/RNMail.m b/RNMail/RNMail.m index 3224d5b..7c77eac 100644 --- a/RNMail/RNMail.m +++ b/RNMail/RNMail.m @@ -70,25 +70,37 @@ RCT_EXPORT_METHOD(mail:(NSDictionary *)options if (options[@"attachments"]) { NSArray *attachments = [RCTConvert NSArray:options[@"attachments"]]; for (NSDictionary *attachment in attachments) { - if (attachment[@"path"] && (attachment[@"type"] || attachment[@"mimeType"])) { + if ((attachment[@"path"] || attachment[@"uri"]) && (attachment[@"type"] || attachment[@"mimeType"])) { NSString *attachmentPath = [RCTConvert NSString:attachment[@"path"]]; + NSString *attachmentUri = [RCTConvert NSString:attachment[@"uri"]]; NSString *attachmentType = [RCTConvert NSString:attachment[@"type"]]; NSString *attachmentName = [RCTConvert NSString:attachment[@"name"]]; NSString *attachmentMimeType = [RCTConvert NSString:attachment[@"mimeType"]]; - NSFileManager *fileManager = [NSFileManager defaultManager]; - if (![fileManager fileExistsAtPath:attachmentPath]){ - callback(@[[NSString stringWithFormat: @"attachment file with path '%@' does not exist", attachmentPath]]); - return; - } - // Set default filename if not specificed if (!attachmentName) { attachmentName = [[attachmentPath lastPathComponent] stringByDeletingPathExtension]; } - // Get the resource path and read the file using NSData - NSData *fileData = [NSData dataWithContentsOfFile:attachmentPath]; + NSData *fileData; + if (attachmentPath) { + NSFileManager *fileManager = [NSFileManager defaultManager]; + if (![fileManager fileExistsAtPath:attachmentPath]){ + callback(@[[NSString stringWithFormat: @"attachment file with path '%@' does not exist", attachmentPath]]); + return; + } + // Get the resource path and read the file using NSData + fileData = [NSData dataWithContentsOfFile:attachmentPath]; + } else if (attachmentUri) { + // Get the URI and read it using NSData + NSURL *attachmentURL = [[NSURLComponents componentsWithString:attachmentUri] URL]; + NSError *error = nil; + fileData = [NSData dataWithContentsOfURL:attachmentURL options:0 error:&error]; + if (!fileData) { + callback(@[[NSString stringWithFormat: @"attachment file with uri '%@' does not exist", attachmentUri]]); + return; + } + } // Determine the MIME type NSString *mimeType; diff --git a/android/src/main/java/com/chirag/RNMail/RNMailModule.java b/android/src/main/java/com/chirag/RNMail/RNMailModule.java index 8460848..e93973e 100644 --- a/android/src/main/java/com/chirag/RNMail/RNMailModule.java +++ b/android/src/main/java/com/chirag/RNMail/RNMailModule.java @@ -99,17 +99,24 @@ public class RNMailModule extends ReactContextBaseJavaModule { ArrayList uris = new ArrayList(); for (int keyIndex = 0; keyIndex < length; keyIndex++) { ReadableMap clip = r.getMap(keyIndex); - if (clip.hasKey("path") && !clip.isNull("path")){ + Uri uri; + if (clip.hasKey("path") && !clip.isNull("path")) { String path = clip.getString("path"); File file = new File(path); - Uri uri = FileProvider.getUriForFile(reactContext, provider, file); - uris.add(uri); + uri = FileProvider.getUriForFile(reactContext, provider, file); + } else if (clip.hasKey("uri") && !clip.isNull("uri")) { + String uriPath = clip.getString("uri"); + uri = Uri.parse(uriPath); + } else { + callback.invoke("not_found"); + return; + } + uris.add(uri); - for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) { - String packageName = resolvedIntentInfo.activityInfo.packageName; - reactContext.grantUriPermission(packageName, uri, - Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); - } + for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) { + String packageName = resolvedIntentInfo.activityInfo.packageName; + reactContext.grantUriPermission(packageName, uri, + Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); } } diff --git a/index.d.ts b/index.d.ts index 90606f1..765abbc 100644 --- a/index.d.ts +++ b/index.d.ts @@ -8,8 +8,9 @@ export namespace Mailer { customChooserTitle?: string; isHTML?: boolean; attachments?: { - path: string; - type?: string; + path?: string; // Specify either 'path' or 'uri' + uri?: string; + type?: string; // Specify either 'type' or 'mimeType' mimeType?: string; name?: string; }[] diff --git a/package.json b/package.json index 79a1e5c..9c2c7ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "6.0.2", + "version": "6.1.0", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From 44d045f5a0ea2b9ceb4cca9e0cb010d039092fc9 Mon Sep 17 00:00:00 2001 From: Geraint White Date: Mon, 29 Mar 2021 14:16:40 +0100 Subject: [PATCH 22/24] Fix not_available issue when targetSdkVersion = 30 (#175) There are changes in Android 11 regarding how apps can query and interact with other apps https://developer.android.com/about/versions/11/privacy/package-visibility. --- android/src/main/AndroidManifest.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 1c61a40..7a86d24 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,6 +1,11 @@ - + + + + + + Date: Mon, 16 Aug 2021 11:26:06 -0400 Subject: [PATCH 23/24] 6.1.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 003d040..9157b08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "react-native-mail", - "version": "6.0.2", + "version": "6.1.1", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 9c2c7ba..e2d84df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-mail", - "version": "6.1.0", + "version": "6.1.1", "description": "A wrapper on top of MFMailComposeViewController from iOS and Mail Intent on android", "author": { "name": "Chirag Jain", From 340618e4ef7f21a29d739d4180c2a267a14093d3 Mon Sep 17 00:00:00 2001 From: Ernestas <36773034+ernestasgobionis@users.noreply.github.com> Date: Mon, 22 Nov 2021 22:20:51 +0200 Subject: [PATCH 24/24] minSdkVersion bump (#187) --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index a988449..7ca2b5a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -5,7 +5,7 @@ android { buildToolsVersion project.hasProperty('buildToolsVersion') ? project.buildToolsVersion : "23.0.1" defaultConfig { - minSdkVersion 16 + minSdkVersion 21 targetSdkVersion project.hasProperty('targetSdkVersion') ? project.targetSdkVersion : 22 versionCode 1 versionName "1.0"