Как отправлять электронные письма из моего приложения Android?

Ответы:

978

Лучший (и самый простой) способ - использовать Intent:

Intent i = new Intent(Intent.ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"recipient@example.com"});
i.putExtra(Intent.EXTRA_SUBJECT, "subject of email");
i.putExtra(Intent.EXTRA_TEXT   , "body of email");
try {
    startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
    Toast.makeText(MyActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}

В противном случае вам придется написать свой собственный клиент.

Джереми Логан
источник
6
В приведенном выше коде нет идентификатора электронной почты отправителя. Затем, как отправить сообщение?
KIRAN KJ
38
КИРАН: Вам нужно разобраться, как работают Интенты, чтобы понять это. По сути, он откроет почтовое приложение с уже заполненным получателем, темой и телом. Это зависит от приложения электронной почты, чтобы сделать отправку.
Джереми Логан
8
Письмо не появляется в поле «TO» при запуске операции. кто-нибудь знает?
Хамза Вакас
11
большой вклад этого комментария: сообщение / rfc822
Гильерме Оливейра
22
добавьте их, чтобы быть уверенным, что chooser отображает только почтовые приложения: Intent i = new Intent(Intent.ACTION_SENDTO); i.setType("message/rfc822"); i.setData(Uri.parse("mailto:"));
Edris
194

Использование .setType("message/rfc822")или выбор покажет вам все (многие) приложения, которые поддерживают намерение отправки.

Джефф С
источник
5
Хорошо, у этого должно быть больше голосов "за". Вы не заметите тестирование на эмуляторе, но когда вы отправите «text / plain» на реальном устройстве, вы получите список из 15+ приложений! поэтому обязательно рекомендуется использовать message / rfc822 (стандарт электронной почты).
Бланделл
7
@Blundell привет, но я не увидел никакой разницы после того, как перешел наmessage/rfc822
ничья
2
Вы можете удалить Bluetooth из списка? Это также обнаруживается с этим типом. +1 хотя, аккуратный трюк!
ingh.am
4
Спас наш бекон. Не могу себе представить, объясняя клиенту, что пользователь может твитить запросы поддержки, а не по электронной почте.
Кевин Галлиган
1
+1111111 Это заслуживает бесконечных +1, чтобы другие могли это увидеть. Я пропустил эту часть, и мне пришлось некоторое время заниматься этой проблемой!
Вызов
89

Я использую это с давних времен, и это кажется хорошим, никаких приложений, не относящихся к электронной почте, не появляется. Просто еще один способ отправить письмо с намерением:

Intent intent = new Intent(Intent.ACTION_SENDTO); // it's not ACTION_SEND
intent.putExtra(Intent.EXTRA_SUBJECT, "Subject of email");
intent.putExtra(Intent.EXTRA_TEXT, "Body of email");
intent.setData(Uri.parse("mailto:default@recipient.com")); // or just "mailto:" for blank
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // this will make such that when user returns to your app, your app is displayed, instead of the email app.
startActivity(intent);
Рэнди Сугианто 'Юку'
источник
1
Неподдерживаемое действие: это действие в настоящее время не поддерживается
erdomester
4
lgor G-> plz изменить с setType "(обычный / текст") на setType ("текст / обычный")
sachit
2
.setType ("message / rfc822") не текст / обычный
The Hungry Androider
1
этот код откроет адрес электронной почты? Как я могу отправить письмо, не показывая намерения пользователю @yuku Я хочу отправить пароль на электронную почту
Erum
2
Этот ответ довольно влиятельный . :)
Ник Волынкин
54

Я использовал что-то вроде принятого в настоящее время ответа, чтобы отправлять электронные письма с приложенным двоичным файлом журнала ошибок. GMail и K-9 отправляют его очень хорошо, и он также приходит нормально на мой почтовый сервер. Единственной проблемой был мой почтовый клиент по выбору Thunderbird, у которого были проблемы с открытием / сохранением прикрепленного файла журнала. Фактически это просто не сохраняло файл вообще без жалоб.

Я взглянул на один из исходных текстов этих писем и заметил, что вложение файла журнала (понятно) имеет тип mime message/rfc822 . Конечно, это вложение не является прикрепленным письмом. Но Thunderbird не может изящно справиться с этой крошечной ошибкой. Это был облом.

После небольшого исследования и экспериментов я нашел следующее решение:

public Intent createEmailOnlyChooserIntent(Intent source,
    CharSequence chooserTitle) {
    Stack<Intent> intents = new Stack<Intent>();
    Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto",
            "info@domain.com", null));
    List<ResolveInfo> activities = getPackageManager()
            .queryIntentActivities(i, 0);

    for(ResolveInfo ri : activities) {
        Intent target = new Intent(source);
        target.setPackage(ri.activityInfo.packageName);
        intents.add(target);
    }

    if(!intents.isEmpty()) {
        Intent chooserIntent = Intent.createChooser(intents.remove(0),
                chooserTitle);
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
                intents.toArray(new Parcelable[intents.size()]));

        return chooserIntent;
    } else {
        return Intent.createChooser(source, chooserTitle);
    }
}

Может использоваться следующим образом:

Intent i = new Intent(Intent.ACTION_SEND);
i.setType("*/*");
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(crashLogFile));
i.putExtra(Intent.EXTRA_EMAIL, new String[] {
    ANDROID_SUPPORT_EMAIL
});
i.putExtra(Intent.EXTRA_SUBJECT, "Crash report");
i.putExtra(Intent.EXTRA_TEXT, "Some crash report details");

startActivity(createEmailOnlyChooserIntent(i, "Send via email"));

Как видите, метод createEmailOnlyChooserIntent можно легко передать с правильным намерением и правильным типом mime.

Затем он просматривает список доступных действий, которые отвечают на намерение mailtoпротокола ACTION_SENDTO (которые являются только приложениями электронной почты), и строит средство выбора на основе этого списка действий и исходного намерения ACTION_SEND с правильным типом mime.

Еще одним преимуществом является то, что Skype больше не указан (что происходит с типом mime rfc822).

tiguchi
источник
1
Я только что вставил фрагмент кода, и он отлично работает. До того, как были перечислены приложения, такие как Google Drive, Skype и т. Д. Но разве нет способа отправить письмо из приложения, не вызывая другое приложение? я только что прочитал статью о почтовом клиенте, который @Rene постет выше, но кажется слишком сложным, чтобы просто отправить простое электронное письмо
Alex Cio
Отличный ответ. У меня были также Skype и Google Drive, ACTION_SENDи это было прекрасно.
Дарренп
1
Самое популярное решение, приведенное выше, возвращает также Skype и Vkontakte. Это решение лучше.
Денис Кутлубаев
что такое crashLogFile? где он инициализирован? pease sepecify
Noufal
@Noufal Это всего лишь остаток от моей собственной базы кода. Это Fileэкземпляр, указывающий на файл журнала сбоев, который мои Android-приложения создают в фоновом режиме на случай возникновения необработанного исключения. Этот пример должен просто иллюстрировать, как добавить вложение электронной почты. Вы также можете прикрепить любой другой файл из внешнего хранилища (например, изображение). Вы также можете удалить эту строку crashLogFile, чтобы получить рабочий пример.
Тигучи
37

Чтобы ПОЛЬЗОВАТЬСЯ ПРИЛОЖЕНИЯМИ ПО ЭЛЕКТРОННОЙ ПОЧТЕ для разрешения вашего намерения, вам нужно указать ACTION_SENDTO как Действие и mailto как Данные.

private void sendEmail(){

    Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
    emailIntent.setData(Uri.parse("mailto:" + "recipient@example.com")); 
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "My email's subject");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "My email's body");

    try {
        startActivity(Intent.createChooser(emailIntent, "Send email using..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(Activity.this, "No email clients installed.", Toast.LENGTH_SHORT).show();
    }

}
wildzic
источник
23

Я решил эту проблему с помощью простых строк кода, как объясняется в документации Android.

( https://developer.android.com/guide/components/intents-common.html#Email )

Наиболее важным является флаг: он есть ACTION_SENDTO, а неACTION_SEND

Другая важная линия

intent.setData(Uri.parse("mailto:")); ***// only email apps should handle this***

Кстати, если вы отправите пустое Extra, то if()в конце не будет работать, и приложение не запустит почтовый клиент.

Согласно документации Android. Если вы хотите убедиться, что ваши намерения обрабатываются только приложением электронной почты (а не другими приложениями для обмена текстовыми сообщениями или социальными приложениями), используйте это ACTION_SENDTOдействие и включите « mailto:» схему данных. Например:

public void composeEmail(String[] addresses, String subject) {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:")); // only email apps should handle this
    intent.putExtra(Intent.EXTRA_EMAIL, addresses);
    intent.putExtra(Intent.EXTRA_SUBJECT, subject);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}
Педро Варела
источник
21

Стратегия использования .setType("message/rfc822")или, по- ACTION_SENDвидимому, также соответствует приложениям, которые не являются почтовыми клиентами, такие как Android Beam и Bluetooth .

Использование ACTION_SENDTOи mailto:URI, кажется, работает отлично, и рекомендуется в документации для разработчиков . Однако, если вы делаете это на официальных эмуляторах и не настроены учетные записи электронной почты (или нет почтовых клиентов), вы получите следующую ошибку:

Неподдерживаемое действие

Это действие в настоящее время не поддерживается.

Как показано ниже:

Неподдерживаемое действие: это действие в настоящее время не поддерживается.

Оказывается, эмуляторы разрешают намерение для вызываемой активности com.android.fallback.Fallback, которая отображает вышеуказанное сообщение. Видимо это по замыслу.

Если вы хотите, чтобы ваше приложение обошло это так, чтобы оно также корректно работало на официальных эмуляторах, вы можете проверить его, прежде чем пытаться отправить электронное письмо:

private void sendEmail() {
    Intent intent = new Intent(Intent.ACTION_SENDTO)
        .setData(new Uri.Builder().scheme("mailto").build())
        .putExtra(Intent.EXTRA_EMAIL, new String[]{ "John Smith <johnsmith@yourdomain.com>" })
        .putExtra(Intent.EXTRA_SUBJECT, "Email subject")
        .putExtra(Intent.EXTRA_TEXT, "Email body")
    ;

    ComponentName emailApp = intent.resolveActivity(getPackageManager());
    ComponentName unsupportedAction = ComponentName.unflattenFromString("com.android.fallback/.Fallback");
    if (emailApp != null && !emailApp.equals(unsupportedAction))
        try {
            // Needed to customise the chooser dialog title since it might default to "Share with"
            // Note that the chooser will still be skipped if only one app is matched
            Intent chooser = Intent.createChooser(intent, "Send email with");
            startActivity(chooser);
            return;
        }
        catch (ActivityNotFoundException ignored) {
        }

    Toast
        .makeText(this, "Couldn't find an email app and account", Toast.LENGTH_LONG)
        .show();
}

Найти больше информации в документации для разработчиков .

Сэм
источник
13

Отправка электронной почты может быть выполнена с помощью Intents, которая не требует настройки. Но тогда это потребует взаимодействия с пользователем, и расположение будет немного ограничено.

Создание и отправка более сложных электронных писем без взаимодействия с пользователем влечет за собой создание собственного клиента. Во-первых, Sun Java API для электронной почты недоступен. Я успешно использовал библиотеку Apache Mime4j для создания электронной почты. Все основано на документах в Nilvec .

Rene
источник
6

Вот пример рабочего кода, который открывает почтовое приложение на Android-устройстве и автоматически заполняется адресами и темами в письме.

protected void sendEmail() {
    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:feedback@gmail.com"));
    intent.putExtra(Intent.EXTRA_SUBJECT, "Feedback");
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    }
}
Шридхар Налам
источник
Спасибо. По сравнению с решением @Avi Parshan вы устанавливаете адрес электронной почты setData(), а Avi - putExtra(). Оба варианта рабочие. Но если удалить setDataи использовать только intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"hi@example.com"});, было бы ActivityNotFoundException.
CoolMind
5

Я использую приведенный ниже код в своих приложениях. Это показывает именно почтовые клиентские приложения, такие как Gmail.

    Intent contactIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", getString(R.string.email_to), null));
    contactIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.email_subject));
    startActivity(Intent.createChooser(contactIntent, getString(R.string.email_chooser)));
Ломжа
источник
5

Это покажет вам только почтовые клиенты (а также PayPal по неизвестной причине)

 public void composeEmail() {

    Intent intent = new Intent(Intent.ACTION_SENDTO);
    intent.setData(Uri.parse("mailto:"));
    intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"hi@example.com"});
    intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
    intent.putExtra(Intent.EXTRA_TEXT, "Body");
    try {
        startActivity(Intent.createChooser(intent, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(MainActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
}
Ави Паршан
источник
1
Отличное решение! Это позволяет избежать многих неподходящих приложений (в основном используется как «Поделиться»). Не добавляйте intent.type = "message/rfc822"; intent.type = "text/html";сюда, так как это приведет к исключению.
CoolMind
3

Вот как я это сделал. Красиво и просто.

String emailUrl = "mailto:email@example.com?subject=Subject Text&body=Body Text";
        Intent request = new Intent(Intent.ACTION_VIEW);
        request.setData(Uri.parse(emailUrl));
        startActivity(request);
Любитель собак
источник
3

Эта функция вначале направляет Gmail с прямым намерением на отправку электронной почты, если Gmail не найден, а затем продвигает средство выбора намерений. Я использовал эту функцию во многих коммерческих приложениях, и она работает нормально. Надеюсь, это поможет вам:

public static void sentEmail(Context mContext, String[] addresses, String subject, String body) {

    try {
        Intent sendIntentGmail = new Intent(Intent.ACTION_VIEW);
        sendIntentGmail.setType("plain/text");
        sendIntentGmail.setData(Uri.parse(TextUtils.join(",", addresses)));
        sendIntentGmail.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail");
        sendIntentGmail.putExtra(Intent.EXTRA_EMAIL, addresses);
        if (subject != null) sendIntentGmail.putExtra(Intent.EXTRA_SUBJECT, subject);
        if (body != null) sendIntentGmail.putExtra(Intent.EXTRA_TEXT, body);
        mContext.startActivity(sendIntentGmail);
    } catch (Exception e) {
        //When Gmail App is not installed or disable
        Intent sendIntentIfGmailFail = new Intent(Intent.ACTION_SEND);
        sendIntentIfGmailFail.setType("*/*");
        sendIntentIfGmailFail.putExtra(Intent.EXTRA_EMAIL, addresses);
        if (subject != null) sendIntentIfGmailFail.putExtra(Intent.EXTRA_SUBJECT, subject);
        if (body != null) sendIntentIfGmailFail.putExtra(Intent.EXTRA_TEXT, body);
        if (sendIntentIfGmailFail.resolveActivity(mContext.getPackageManager()) != null) {
            mContext.startActivity(sendIntentIfGmailFail);
        }
    }
}
Шохан Ахмед Сиян
источник
1
Большое спасибо. Спаси мою жизнь
androCoder-BD
2

просто попробуйте этот

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    buttonSend = (Button) findViewById(R.id.buttonSend);
    textTo = (EditText) findViewById(R.id.editTextTo);
    textSubject = (EditText) findViewById(R.id.editTextSubject);
    textMessage = (EditText) findViewById(R.id.editTextMessage);

    buttonSend.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            String to = textTo.getText().toString();
            String subject = textSubject.getText().toString();
            String message = textMessage.getText().toString();

            Intent email = new Intent(Intent.ACTION_SEND);
            email.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
            // email.putExtra(Intent.EXTRA_CC, new String[]{ to});
            // email.putExtra(Intent.EXTRA_BCC, new String[]{to});
            email.putExtra(Intent.EXTRA_SUBJECT, subject);
            email.putExtra(Intent.EXTRA_TEXT, message);

            // need this to prompts email client only
            email.setType("message/rfc822");

            startActivity(Intent.createChooser(email, "Choose an Email client :"));

        }
    });
}
NagarjunaReddy
источник
3
Как это может быть лучше, чем ответы, которые уже существовали, когда вы опубликовали это? Это просто выглядит как копия принятого ответа, завернутого в упражнении.
Сэм
2

Другое решение может быть

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
emailIntent.setType("plain/text");
emailIntent.setClassName("com.google.android.gm", "com.google.android.gm.ComposeActivityGmail");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[]{"someone@gmail.com"});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Yo");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Hi");
startActivity(emailIntent);

Предполагая, что на большинстве устройств Android уже установлено приложение GMail.

silentsudo
источник
@PedroVarela мы всегда можем проверить активность не найден исключение.
Silentsudo
1
Да мы можем. Но ваше решение не является правильным. В документации Android четко указано, что вам нужно сделать, чтобы показывать только почтовые приложения в средстве выбора. Вы написали «Предполагая, что на большинстве устройств Android уже установлено приложение Gmail»; Что делать, если это корневое устройство и пользователь удаляет клиент Gmail? Предположим, вы создаете собственное почтовое приложение ?, если пользователь собирается отправить электронное письмо, ваше приложение не будет в этом списке. Что произойдет, если Gmail изменит имя пакета? Собираетесь ли вы обновить свое приложение?
Педро Варела
2

Используйте это для отправки электронной почты ...

boolean success = EmailIntentBuilder.from(activity)
    .to("support@example.org")
    .cc("developer@example.org")
    .subject("Error report")
    .body(buildErrorReport())
    .start();

используйте build gradle:

compile 'de.cketti.mailto:email-intent-builder:1.0.0'
Manish
источник
2

Я использовал этот код для отправки почты, непосредственно запустив раздел создания почтового приложения по умолчанию.

    Intent i = new Intent(Intent.ACTION_SENDTO);
    i.setType("message/rfc822"); 
    i.setData(Uri.parse("mailto:"));
    i.putExtra(Intent.EXTRA_EMAIL  , new String[]{"test@gmail.com"});
    i.putExtra(Intent.EXTRA_SUBJECT, "Subject");
    i.putExtra(Intent.EXTRA_TEXT   , "body of email");
    try {
        startActivity(Intent.createChooser(i, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }
Фарис Мухаммед
источник
1

Этот метод работает для меня. Он открывает приложение Gmail (если установлено) и устанавливает mailto.

public void openGmail(Activity activity) {
    Intent emailIntent = new Intent(Intent.ACTION_VIEW);
    emailIntent.setType("text/plain");
    emailIntent.setType("message/rfc822");
    emailIntent.setData(Uri.parse("mailto:"+activity.getString(R.string.mail_to)));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, activity.getString(R.string.app_name) + " - info ");
    final PackageManager pm = activity.getPackageManager();
    final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, 0);
    ResolveInfo best = null;
    for (final ResolveInfo info : matches)
        if (info.activityInfo.packageName.endsWith(".gm") || info.activityInfo.name.toLowerCase().contains("gmail"))
            best = info;
    if (best != null)
        emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
    activity.startActivity(emailIntent);
}
псих
источник
1
/**
 * Will start the chosen Email app
 *
 * @param context    current component context.
 * @param emails     Emails you would like to send to.
 * @param subject    The subject that will be used in the Email app.
 * @param forceGmail True - if you want to open Gmail app, False otherwise. If the Gmail
 *                   app is not installed on this device a chooser will be shown.
 */
public static void sendEmail(Context context, String[] emails, String subject, boolean forceGmail) {

    Intent i = new Intent(Intent.ACTION_SENDTO);
    i.setData(Uri.parse("mailto:"));
    i.putExtra(Intent.EXTRA_EMAIL, emails);
    i.putExtra(Intent.EXTRA_SUBJECT, subject);
    if (forceGmail && isPackageInstalled(context, "com.google.android.gm")) {
        i.setPackage("com.google.android.gm");
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
    } else {
        try {
            context.startActivity(Intent.createChooser(i, "Send mail..."));
        } catch (ActivityNotFoundException e) {
            Toast.makeText(context, "No email app is installed on your device...", Toast.LENGTH_SHORT).show();
        }
    }
}

/**
 * Check if the given app is installed on this devuice.
 *
 * @param context     current component context.
 * @param packageName The package name you would like to check.
 * @return True if this package exist, otherwise False.
 */
public static boolean isPackageInstalled(@NonNull Context context, @NonNull String packageName) {
    PackageManager pm = context.getPackageManager();
    if (pm != null) {
        try {
            pm.getPackageInfo(packageName, 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }
    return false;
}
Гал Ром
источник
1
 Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
            "mailto","ebgsoldier@gmail.com", null));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Forgot Password");
    emailIntent.putExtra(Intent.EXTRA_TEXT, "Write your Pubg user name or Phone Number");
    startActivity(Intent.createChooser(emailIntent, "Send email..."));**strong text**
Тусиф Акрам
источник
1

Попробуй это:

String mailto = "mailto:bob@example.org" +
    "?cc=" + "alice@example.com" +
    "&subject=" + Uri.encode(subject) +
    "&body=" + Uri.encode(bodyText);

Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse(mailto));

try {
    startActivity(emailIntent);
} catch (ActivityNotFoundException e) {
    //TODO: Handle case where no email app is available
}

Приведенный выше код откроет любимый почтовый клиент пользователей, предварительно заполненный электронным письмом, готовым к отправке.

Источник

Дэн Брей
источник