如何在带有http的dart中使用Mailgun添加附件?

问题描述

Mailgun正式支持http,但是截止2020年9月,Dart没有官方软件包。电子邮件发送成功,但附件丢失。注意所有失败的尝试。

import 'dart:io';
import 'package:http/http.dart' as foo;

// must be https for basic auth (un + pw)
const secureProtocol = 'https://';
const host = 'api.mailgun.net/v3/m.givenapp.com/messages';

// basic auth
const userApiKey = 'my api key here'; // pw
const un = 'api';

void main() async {
  //
  const path = 'bin/services/foo.baz.txt';
  var file = File(path);
  print(file.existsSync()); // looks good
  print(file.readAsstringSync()); // looks good
  var list = <String>[];
  list.add(file.readAsstringSync());
  var files = <File>[];
  files.add(file);
  //
  var body = <String,dynamic>{};
  body.putIfAbsent('from',() => 'John Smith <john.smith@example.com>');
  body.putIfAbsent('to',() => 'jane.doe@somehost.com');
  body.putIfAbsent('subject',() => 'test subject  ' + DateTime.Now().toIso8601String());
  body.putIfAbsent('text',() => 'body text');

  // fixme
  body.putIfAbsent('attachment',() => '@$path'); // Failed
  body.putIfAbsent('attachment',() => path); // Failed
  //body.putIfAbsent('attachment',() => file); // Failed
  //body.putIfAbsent('attachment',() => list); // Failed
  //body.putIfAbsent('attachment',() => files); // Failed
  body.putIfAbsent('attachment',() => file.readAsstringSync()); // Failed
  //body.putIfAbsent('attachment',() => file.readAsBytesSync()); // Failed

  final uri = '$secureProtocol$un:$userApiKey@$host';

  final response = await foo.post(uri,body: body);

  print('Response status: ${response.statusCode}');
  print('Response body: ${response.body}');
}

我想我已经接近了。

https://documentation.mailgun.com/en/latest/api-sending.html#sending

解决方法

您链接的文档说

重要提示:发送附件时必须使用多部分/表单数据编码。

因此,您想执行MultipartRequest,而不仅仅是普通的发帖请求。

这可以使用与您已经在使用的http包相同的以下代码来大致完成。

var request = foo.MultipartRequest(
  'POST',Uri.parse('$secureProtocol$un:$userApiKey@$host')
);

var body = <String,dynamic>{};
body.putIfAbsent('from',() => 'John Smith <john.smith@example.com>');
body.putIfAbsent('to',() => 'jane.doe@somehost.com');
body.putIfAbsent('subject',() => 'test subject  ' + DateTime.now().toIso8601String());
body.putIfAbsent('text',() => 'body text');

request.fields = body;

request.headers["Content-Type"] = "multipart/form-data";
request.files.add(await http.MultipartFile.fromPath('attachment',path));

var response = await request.send();
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');

所有操作都与添加from,to,subject和text字段相同,只需将其添加到fields的{​​{1}}参数中即可。

已更改标题以指示正确的类型。从该路径创建一个MultipartRequest,并为其指定字段名称为MultipartFile。它将添加到attachment的文件部分。

然后,该请求的发送和处理方式与您已有的类似。


如果您想更轻松地执行此操作,可以尝试mailgun package,它会为您完成所有这些操作。