i am trying to send a recently in app - captured photo by mail and am encountering the following error:
(for the mailing functionality i am using this module : var Mailer = require('NativeModules').RNMail;
I am trying to send a photo by mail with the help of this module and get the following error:
index.ios.bundle:28842Exception '-[MFMailComposeInternalViewController addAttachmentData:mimeType:fileName:] attachment must not be nil.' was thrown while invoking mail on target RNMail with params (
{
attachment = {
name = Ladunek;
path = "assets-library://asset/asset.JPG?id=3B7DBB2E-1271-4D86-A5F2-A0CEEE7CC4DE&ext=JPG";
type = jpg;
};
body = "body";
isHTML = 1;
recipients = (
"[email protected]"
);
subject = Ladunek;
},
9
)
This is the invoking code :
.then((data, path) => {
console.log(data)
console.log(data.path)
Mailer.mail({
subject: 'Ladunek',
recipients: ['[email protected]'],
body: 'body',
isHTML: true, // iOS only, exclude if false
attachment: {
path: data.path, // The absolute path of the file from which to read data.
type: 'jpg', // Mime Type: jpg, png, doc, ppt, html, pdf
name: 'Ladunek', // Optional: Custom filename for attachment
}
}, (error, event) => {
if(error) {
AlertIOS.alert('Error', 'Could not send mail. Please send a mail to [email protected]');
}
});
})
Is the path invalid? Or might it be something else.
EDIT
I am obtaining the file path with this module react-native-camera
like so:
Event:
takePicture() {
this.camera.capture()
.then((data, path) =>
Element:
<Camera
ref={(cam) => {
this.camera = cam;
}}
style={{
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
height: 400,
width: Dimensions.get('window').width
}}
aspect={Camera.constants.Aspect.fill}>
<Text style={{
flex: 0,
backgroundColor: '#fff',
borderRadius: 5,
color: '#000',
padding: 10,
margin: 40
}} onPress={this.takePicture.bind(this)}>{cameraIcon}</Text>
</Camera>
UPDATE2
After including an obj-c file for uri to path transformation I am receiving the following error now:
ExceptionsManager.js:76 JSON value '<null>' of type NSNull cannot be converted to NSString
Did I "remove" the wrong lines from the following code? :/
Obj-c File content:
#import "RCTBridgeModule.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <UIKit/UIKit.h>
@interface ReadImageData : NSObject <RCTBridgeModule>
@end
@implementation ReadImageData
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(readImage:(NSString *)input callback:(RCTResponseSenderBlock)callback)
{
// Create NSURL from uri
NSURL *url = [[NSURL alloc] initWithString:input];
// Create an ALAssetsLibrary instance. This provides access to the
// videos and photos that are under the control of the Photos application.
//ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
// Using the ALAssetsLibrary instance and our NSURL object open the image.
//[library assetForURL:url resultBlock:^(ALAsset *asset) {
// Create an ALAssetRepresentation object using our asset
// and turn it into a bitmap using the CGImageRef opaque type.
//CGImageRef imageRef = [asset thumbnail];
// Create UIImageJPEGRepresentation from CGImageRef
// NSData *imageData = UIImageJPEGRepresentation([UIImage imageWithCGImage:imageRef], 0.1);
// Convert to base64 encoded string
// NSString *base64Encoded = [imageData base64EncodedStringWithOptions:0];
callback(@[url]);
//} failureBlock:^(NSError *error) {
//NSLog(@"that didn't work %@", error);
//}];
}
@end
Another, more robust approach to sending emails in React Native will be with external third-party services. Instead of launching a user’s email app to send an email, we’ll start sending emails to users in the background. These can be registration emails, password resets or anything else that makes sense to be sent once triggered.
How to Upload File/Image to Server with Form Data in React Native 1 Uploading File in React Native 2 To Make a React Native App 3 Installation of Dependency 4 Linking of Dependency 5 CocoaPods Installation 6 Code for the File Upload in React Native 7 Server Side PHP Code 8 To Run the React Native App 9 Output Screenshots More ...
We do this using Expo for React Native, and that’s it, no third party packages or native bridges — just the official modules of Expo. As a backend we simply use Node.js with Express, where we receive the image converted to base64 via a Post Request and save it directly to our server as an image file using the FileSystem Module (fs). Here we go:
We are going to use react-native init to make our React Native App. Assuming that you have node installed, you can use npm to install the react-native-cli command line utility. Open the terminal and go to the workspace and run
------ EDITED ANSWER BELOW ------
Okay, so I finally have a Mac and was able to look into this issue in more details.
This is what I found for both Android and iOS.
The assumption is that you are using react-native-camera together with react-native-mail
- 1: Absolute Path
Add property captureTarget={Camera.constants.CaptureTarget.disk}
to Camera
component like so:
<Camera
captureTarget={Camera.constants.CaptureTarget.disk}
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}>
<Text style={styles.capture} onPress={this.takePicture.bind(this)}>[CAPTURE]</Text>
</Camera>
Now camera component should return absolute file path instead of uri.
So for Android you should see something like this:
"file:///storage/emulated/0/Pictures/RCTCameraModule/IMG_20160730_060652.jpg"
instead of:
"content://media/external/images/media/86"
and for iOS you should get something like this:
"/Users/anton/Library/Developer/CoreSimulator/Devices/9A15F203-9A58-41C5-A4FC-EA25FAAE92BD/data/Containers/Data/Application/79FF93F9-BA89-4F4C-8809-277BEECD447D/Documents/EFFF0ECE-4063-4FE5-984E-E76506788350.jpg"
instead of:
"assets-library://asset/asset.JPG?id=0058FA4A-268F-408A-9150-017A3DA368D2&ext=JPG"
- 2: Pitfalls
iOS:
If Apple's MFMailComposeViewController crashes and you see the following error message:
This is most likely because you are running the app on iOS 9 Simulator. Solution: either test the app on real device, or download an older Simulator such as iOS 8.4.
More information on this issue can be found here
Android:
As of this writing there is no attachment support for Android.
Solution: (PR has been made to add this feature, but if you can't wait)
Add the following code to file RNMAILModule.java
if (options.hasKey("attachment") && !options.isNull("attachment")) {
i.putExtra(Intent.EXTRA_STREAM, Uri.parse(options.getMap("attachment").getString("path")));
}
When both Android and iOS work you should have something like this:
And here is the working code:
var Mailer = require('NativeModules').RNMail;
import Camera from 'react-native-camera';
import React, {Component} from 'react';
import
{
View,
TouchableHighlight,
Text,
StyleSheet,
Dimensions,
CameraRoll
}
from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1
},
preview: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
height: Dimensions.get('window').height,
width: Dimensions.get('window').width
},
capture: {
flex: 0,
backgroundColor: '#fff',
borderRadius: 5,
color: '#000',
padding: 10,
margin: 40
}
});
class SendPhoto extends Component {
takePicture() {
this.camera.capture()
.then((data) => {
console.log(data.path)
Mailer.mail({
subject: 'Ladunek',
recipients: ['[email protected]'],
body: 'body',
isHTML: true, // iOS only, exclude if false
attachment: {
path: data.path, // The absolute path of the file from which to read data.
type: 'jpg', // Mime Type: jpg, png, doc, ppt, html, pdf
name: 'Ladunek', // Optional: Custom filename for attachment
}
}, (error, event) => {
if(error) {
AlertIOS.alert('Error', 'Could not send mail. Please send a mail to [email protected]');
}
})
})
.catch(err => console.error(err));
}
render() {
return(
<View>
<View style={styles.container}>
<Camera
captureTarget={Camera.constants.CaptureTarget.disk}
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={Camera.constants.Aspect.fill}>
<Text style={styles.capture} onPress={this.takePicture.bind(this)}>[CAPTURE]</Text>
</Camera>
</View>
</View>
);
}
}
export default SendPhoto;
------ OLD ANSWER BELOW ------
I never used this module before, but it looks like it expects absolute path of the file, however you are providing a file uri.
How are you obtaining this file uri?
Try using react-native-get-real-path module to see if it helps, you can find it here: react-native-get-real-path
i.e. convert your file uri to obtain real path, and use that as path
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With