我使用NSMutableURLRequest发送POST数据到使用SendGrid发送电子邮件的服务器端PHP脚本。这工作得很好。然而,我不知道如何包装UIImagedata正确发送作为附件。下面是我当前的代码:
// Choose an image from your photo library
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
chosenImage = info[UIImagePickerControllerEditedImage]; // chosenImage = UIImage
pickedData = UIImagePNGRepresentation(chosenImage); // pickedData = NSData
attachment = TRUE;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
-(void)sendMail {
toEmailAddress = @"blabla@blabla.com";
subject = @"Some Subject";
message = @"Some message...";
fullName = @"Mister Bla Bla";
if (attachment == TRUE) {
// Create NSData object as PNG image data from camera image
NSString *picAttachment = [NSString stringWithFormat:@"%lu",(unsigned long)[pickedData length]];
NSString *picName = @"Photo";
post = [NSString stringWithFormat:@"&toEmailAddress=%@&subject=%@&message=%@&fullName=%@&picAttachment=%@&picName=%@", toEmailAddress, subject, message, fullName, picAttachment, picName];
} else {
post = [NSString stringWithFormat:@"&toEmailAddress=%@&subject=%@&message=%@&fullName=%@", toEmailAddress, subject, message, fullName];
}
NSData * postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSString * postLength = [NSString stringWithFormat:@"%lu",(unsigned long)[postData length]];
NSMutableURLRequest * request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.someURL.com/sendgrid.php"]]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
// send the POST request, and read the reply by creating a new NSURLSession:
NSURLSession *conn = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[conn dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"requestReply: %@", requestReply); // Return response from PHP script on server.
}] resume];
}
如果你研究这个问题,你可能会发现有一个现有的iOS SendGrid库。不幸的是,这不是答案。SendGrid的人告诉我,出于安全考虑,不要使用这个库。
新答案:
要将文件作为电子邮件附件直接上传到SendGrid,您应该使用Web API v3并创建文档中描述的请求。
首先,您需要在请求中添加身份验证头。其次,需要将数据转换为JSON格式。如果我们讨论的是文件,则需要使用Base64对文件数据进行编码,如正文参数部分所述:
JSON PARAMETER: attachements/content
TYPE: string
REQUIRED: Yes
The Base64 encoded content of the attachment.
另外,看看disposition
和content_id
参数:它们将帮助您设置邮件中的文件外观。
老答:
上传参数和文件的标准方式是使用POST请求和多部分消息。我已经改变了你的代码来创建这种格式的数据:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage* image = info[UIImagePickerControllerEditedImage];
NSDictionary* params = @{
@"toEmailAddress" : @"blabla@blabla.com",
@"subject" : @"Some Subject",
@"message" : @"Some message...",
@"fullName" : @"Mister Bla Bla",
};
[picker dismissViewControllerAnimated:YES completion:^{
[self sendMailWithParams:params image:image];
}];
}
static NSStringEncoding const kEncoding = NSUTF8StringEncoding;
- (void)sendMailWithParams:(NSDictionary*)params image:(UIImage*)image {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
request.URL = [NSURL URLWithString:@"http://www.someURL.com/sendgrid.php"];
request.HTTPMethod = @"POST";
NSString *boundary = [NSUUID UUID].UUIDString;
// define POST request as multipart
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
// prepare boundary
NSString *middleBoundary = [NSString stringWithFormat:@"--%@rn", boundary];
NSData *middleBoundaryData = [middleBoundary dataUsingEncoding:kEncoding];
NSMutableData* body = [NSMutableData data];
// append params
[params enumerateKeysAndObjectsUsingBlock:^(NSString* key, NSString* value, BOOL* stop) {
[body appendData:middleBoundaryData];
NSData* fieldData = [self dataForKey:key value:value];
[body appendData:fieldData];
}];
// append image
if (image) {
[body appendData:middleBoundaryData];
NSData* imageData = [self dataForImage:image imageName:@"photo.png"];
[body appendData:imageData];
}
// add last boundary
NSString* lastBoundary = [NSString stringWithFormat:@"--%@--rn", boundary];
NSData* lastBoundaryData = [lastBoundary dataUsingEncoding:kEncoding];
[body appendData:lastBoundaryData];
// set body to request
request.HTTPBody = body;
// add length of body
NSString *length = [NSString stringWithFormat:@"%llu", (uint64_t)body.length];
[request setValue:length forHTTPHeaderField:@"Content-Length"];
// send request
NSURLSession* session = [NSURLSession sharedSession];
NSURLSessionDataTask* task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
// handle as you want
}];
[task resume];
}
- (NSData*)dataForImage:(UIImage*)image imageName:(NSString*)imageName {
NSString* fieldDescription = [NSString stringWithFormat:
@"Content-Disposition: form-data; name="image"; filename="%@"rn"
@"Content-Type: image/pngrnrn", imageName];
NSMutableData *data = [NSMutableData data];
[data appendData:[fieldDescription dataUsingEncoding:kEncoding]];
NSData* imageData = UIImagePNGRepresentation(image);
[data appendData:imageData];
NSString* newLine = @"rn";
NSData* newLineData = [newLine dataUsingEncoding:kEncoding];
[data appendData:newLineData];
return data;
}
- (NSData*)dataForKey:(NSString*)key value:(NSString*)value {
NSString* fieldDescription = [NSString stringWithFormat:
@"Content-Disposition: form-data; name="%@"rnrn"
@"%@rn", key, value];
return [fieldDescription dataUsingEncoding:kEncoding];
}
可以使用$_POST和$_FILES变量来访问PHP脚本中加载的数据。如果您想了解更多关于多部分消息的信息,请查看这里的文档