Flutter如何使用url_launcher URI发送邮件

10

我在我的应用程序中使用url_launcher和系统邮件发送电子邮件。我使用下面的代码,这个人做得非常好。

void launchEmailSubmission() async {
    final Uri params = Uri(
      scheme: 'mailto',
      path: 'myOwnEmailAddress@gmail.com',
    );
    String url = params.toString();
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      print('Could not launch $url');
    }
  }

但现在我想在邮件正文框中设置“默认”主题和提示文本(如果无法设置提示文本,那么就是普通文本)。

有没有办法实现这个需求?


我发现其他答案存在问题。这个链接应该是你所需要的全部内容:https://dev59.com/g73pa4cB1Zd3GeqPclu3#72030419 - Kyle Venn
7个回答

18

尝试在Uri中使用queryParameters。您可以通过以下方式实现:

void launchEmailSubmission() async {
    final Uri params = Uri(
      scheme: 'mailto',
      path: 'myOwnEmailAddress@gmail.com',
      queryParameters: {
        'subject': 'Default Subject',
        'body': 'Default body'
      }
    );
    String url = params.toString();
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      print('Could not launch $url');
    }
  }
它将默认打开正文和主题。

3
谢谢!它的运行非常好,但有一件事情没有解决,就如我们所预料的那样...当电子邮件应用程序出现时,“默认”和“主题”或“默认”和“正文”之间的空格会被翻译成“+”符号。 有没有什么酷的方法可以使这个“+”符号在Flutter代码之外的电子邮件应用程序中恢复正常的空格? - tsitixe
7
@tsitixe 使用 query: 'subject=默认主题&body=默认内容' 替换 queryParameters: {'subject': '默认主题', 'body': '默认内容'} 以消除 '+' 符号。 - evgen shein
我相信在你的“默认主题”或“默认正文”中出现等号也会导致此问题。 - martinseal1987
你也能像这样打开共享窗口吗? - Samuel Quiroz

7
正如 @tsitixe 所指出的那样,您可以使用Piyushs的答案,并像这样更改 queryParameters 以避免在电子邮件中的单词之间出现“+”符号:
void launchEmailSubmission() async {
    final Uri params = Uri(
    scheme: 'mailto',
    path: 'myOwnEmailAddress@gmail.com',
    query: 'subject=Default Subject&body=Default body'
);

String url = params.toString();
    if (await canLaunch(url)) {
    await launch(url);
} else {
    print('Could not launch $url');
}

}


2

不要忘记在你的 AndroidManifest.xml 中添加以下内容:

<queries>
  <!-- If your app opens https URLs -->
  <intent>
    <action android:name="android.intent.action.VIEW" />
    <data android:scheme="https" />
  </intent>
  <!-- If your app makes calls -->
  <intent>
    <action android:name="android.intent.action.DIAL" />
    <data android:scheme="tel" />
  </intent>
  <!-- If your app emails -->
  <intent>
    <action android:name="android.intent.action.SEND" />
    <data android:mimeType="*/*" />
  </intent>
</queries>

2

试试这个!

void _launchURL() async {
    final Uri params = Uri(
      scheme: 'mailto',
      path: 'my.mail@example.com',
    );
    String  url = params.toString();
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      print( 'Could not launch $url');
    }
  }

1
兄弟..这个代码跟我之前用的原始SO代码完全一样。我建议使用@Maurya上面的代码来添加“默认主题和正文”选项! - tsitixe

1

我们采用了各种方法的一点点。它考虑以下事项:

  • 它将在Web上工作(canLaunch 在Web上不起作用,因此请使用try/catch替换)。
  • 如果没有邮件客户端可用,它会回退到使用剪贴板
  • 它使用帮助函数正确编码主题和正文(否则您将得到+而不是空格

用法

await EmailUtils.launchEmailSubmission(
         toEmail: 'info@catfacts.co',
         subject: 'I love this app',
         body: 'Your feedback below: \n');

email_utils.dart

import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';

class EmailUtils {
  
  /// Example
  /// ```dart
  /// await EmailUtils.launchEmailSubmission(
  ///       toEmail: 'info@catfacts.co',
  ///       subject: 'I love this app',
  ///       body: 'Your feedback below: \n');
  /// ```
  void launchEmailSubmission({
    required String toEmail,
    required String subject,
    required String body,
  }) async {
    String mailUrl = _getEmailString(toEmail: toEmail, subject: subject, body: body)
    // Use `try` instead of `canLaunch` because it doesn't work on web
    try {
      await launch(mailUrl);
    } catch (e) {
      await Clipboard.setData(ClipboardData(text: '$subject \n $body'));
      // Toast to user it was copied to clipboard
    }
  }

  static String _getEmailString({
    required String toEmail,
    required String subject,
    required String body,
  }) {
    final Uri emailReportUri = Uri(
      scheme: 'mailto',
      path: toEmail,
      query: _encodeQueryParameters(<String, String>{
        'subject': subject,
        'body': body,
      }),
    );

    return emailReportUri.toString();
  }

  /// Using `queryParameters` above encodes the text incorrectly.
  /// We use `query` and this helper function to encode properly.
  static String? _encodeQueryParameters(Map<String, String> params) {
    return params.entries
        .map((e) =>
            '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}')
        .join('&');
  }
}

1

除了@Can-Kaplan的答案之外,截至2023年1月launchcanLaunch已经被废弃,应该分别替换为launchUrlcanLaunchUrl

因此,更新后的代码将是:

Future<void> launchEmailSubmission() async {
  final Uri params = Uri(
        scheme: 'mailto',
        path: 'myOwnEmailAddress@gmail.com',
        query: 'subject=Default Subject&body=DefaultBody');

    if (await canLaunchUrl(params)) {
      await launchUrl(params);
    } else {
      log('Could not launch $params');
    }
}

需要注意的是,以下内容必须添加到android>app>src>main>AndroidManifest.xml中。

  <queries>
    <intent>
      <action android:name="android.intent.action.SENDTO" />
      <data android:scheme="mailto" />
    </intent>
  </queries>

希望这能有所帮助。


1

'canLaunch'已被弃用,不应再使用。请改用canLaunchUrl。

让我们使用它

import 'package:url_launcher/url_launcher.dart';   
//...
final Uri params = Uri(
    scheme: 'mailto',
    path: 'admin@gmail.com',
    queryParameters: {
      'subject': 'Default Subject',
      'body': 'Default body'
    }
);
if (await canLaunchUrl(params)) {
  await launchUrl(params);
} else {
  print('Could not launch $params');
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接