You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android发送带附件SMTP邮件时触发File Not Found Exception求助

Fixing SMTP Email File Not Found Exception with ACTION_GET_CONTENT Uri

I've run into this exact issue before—here's what's going wrong and how to fix it:

The Root Cause

When you use Intent.ACTION_GET_CONTENT to pick a file, the returned Uri is a content URI (e.g., content://com.android.providers.media.documents/document/image%3A1234), not a direct file system path. If you try to use this URI as a file path for your SMTP client, it will throw a FileNotFoundException because that path doesn't exist in the device's file system.

Additionally, on Android 10+ (API 29+), Scoped Storage restricts direct access to file system paths, so even if you tried to convert the content URI to a real path, it might not work for all file types.

The Solution: Use Input Streams Instead of File Paths

The best approach is to use the ContentResolver to open an input stream directly from the content URI, then pass that stream to your SMTP attachment handler. This avoids needing a file path entirely and works with all content URIs, regardless of the source.

Here's a revised version of your code that implements this fix:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == RESULT_SUCCESS && resultCode == RESULT_OK && data != null) {
        Uri fileUri = data.getData();
        new Thread(() -> {
            try {
                // Get access to the content resolver
                ContentResolver contentResolver = getContentResolver();
                // Open an input stream from the content URI
                InputStream fileInputStream = contentResolver.openInputStream(fileUri);
                // Fetch the original filename of the attachment
                String attachmentFileName = getAttachmentFileName(contentResolver, fileUri);

                // Configure SMTP properties (fill in your details)
                Properties smtpProps = new Properties();
                smtpProps.put("mail.smtp.host", "your_smtp_host"); // e.g., "smtp.gmail.com"
                smtpProps.put("mail.smtp.port", "587"); // Common TLS port
                smtpProps.put("mail.smtp.auth", "true");
                smtpProps.put("mail.smtp.starttls.enable", "true");

                // Create SMTP session with authentication
                Session session = Session.getInstance(smtpProps, new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication("your_email@example.com", "your_email_password");
                    }
                });

                // Build the email message
                MimeMessage message = new MimeMessage(session);
                message.setFrom(new InternetAddress("your_email@example.com"));
                message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("recipient@example.com"));
                message.setSubject("Email with Attachment");

                // Create the main message body
                MimeBodyPart messageBody = new MimeBodyPart();
                messageBody.setText("Attached is the file you selected.");

                // Create the attachment part using the input stream
                MimeBodyPart attachmentBody = new MimeBodyPart();
                // Use ByteArrayDataSource to wrap the input stream with the correct MIME type
                attachmentBody.setDataHandler(new DataHandler(
                    new ByteArrayDataSource(fileInputStream, contentResolver.getType(fileUri))
                ));
                attachmentBody.setFileName(attachmentFileName);

                // Combine body and attachment into a multipart message
                Multipart multipart = new MimeMultipart();
                multipart.addBodyPart(messageBody);
                multipart.addBodyPart(attachmentBody);

                message.setContent(multipart);

                // Send the email
                Transport.send(message);
                fileInputStream.close(); // Don't forget to close the stream!

                // Update UI on the main thread
                runOnUiThread(() -> 
                    Toast.makeText(getApplicationContext(), "Email sent successfully!", Toast.LENGTH_SHORT).show()
                );

            } catch (Exception e) {
                e.printStackTrace();
                runOnUiThread(() -> 
                    Toast.makeText(getApplicationContext(), "Error sending email: " + e.getMessage(), Toast.LENGTH_LONG).show()
                );
            }
        }).start();
    }
}

// Helper method to get the filename from a content URI
private String getAttachmentFileName(ContentResolver resolver, Uri uri) {
    String fileName = "attachment";
    Cursor cursor = resolver.query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null);
    if (cursor != null && cursor.moveToFirst()) {
        int nameColumnIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        if (nameColumnIndex != -1) {
            fileName = cursor.getString(nameColumnIndex);
        }
        cursor.close();
    }
    return fileName;
}

Key Notes

  • Permission Check: Make sure you have the INTERNET permission declared in your AndroidManifest.xml:
    <uses-permission android:name="android.permission.INTERNET" />
    
    You don't need storage permissions here because ACTION_GET_CONTENT grants temporary access to the selected file via the content URI.
  • Background Execution: Always run SMTP operations in a background thread (as shown in the example) to avoid blocking the main thread and causing ANRs.
  • MIME Types: Using contentResolver.getType(fileUri) ensures the attachment uses the correct MIME type, which helps email clients render the attachment properly.

内容的提问来源于stack exchange,提问作者Muhammad Huzaifa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:53:20