Problem adding email attachments

Xamarin Forms .NET Standard Project problem adding email attachments for Android and iOS

Hi, I'm having a problem with my project.
Project is created in Visual Studio 2017.
Xamarin Forms .NET Standard Project.
NuGet Packages are:
NETStandard.Library v2.0.3.a
Xam.Plugins.Messaging v5.2.0.
Xamarin.Forms v3.1.0.697729.

I'm trying to add an email attachment.
I can get it working in Windows, but can't get it to work for Android or iOS.
The error I get is: Java.Lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference.

The file being attached is dynamically created and the name for this file is always different.
I read somewhere that I need to use FileProvider to add attachments, but I'm not sure how that works or if it applies to dynamically created files.

I'm using the Plugin.Messaging namespace to send the email.

The code is:

//Attempt to open default email client to send email
public bool Email(string To, string Subject, string Body, string AttachmentPathnFilename = "")
{
IEmailTask EmailTask = CrossMessaging.Current.EmailMessenger;
EmailMessageBuilder MyEmailCreated = new EmailMessageBuilder();
MyEmailCreated.To(To);
MyEmailCreated.Subject(Subject);
MyEmailCreated.Body(Body);

        if (AttachmentPathnFilename != "")
        {
            //Replace Jobs dir with Attachment Dir
            AttachmentPathnFilename = AttachmentPathnFilename.Replace("Jobs", "Attachments");

            //Change filename to htm file type
            AttachmentPathnFilename = AttachmentPathnFilename.Replace(Path.GetFileName(AttachmentPathnFilename), Path.GetFileNameWithoutExtension(AttachmentPathnFilename) + ".htm");
            MyEmailCreated.WithAttachment(AttachmentPathnFilename, "text/html");
        }

        IEmailMessage MyEMail = MyEmailCreated.Build();

        if (EmailTask.CanSendEmail)
        {
            EmailTask.SendEmail(MyEMail);
            return true;
        }
        else
        {
            return false;
        }
    }

AttachmentPathnFilename value for Android is "/data/data/com.companyname.project/files/.local/share/Attachments/2019-07-21_11-46-8-Job.txt"
Any help would be greatly appreciated.

Answers

  • Ww_Ww_ Member

    have you set the permission?

  • FWAdminFWAdmin Member ✭✭
    Yes. Both for read and write to external storage. I create the file without any error, just can't attach it.
  • FWAdminFWAdmin Member ✭✭
    edited August 2

    In AndroidManifest.xml the following permissions have been set:

      <uses-permission android:name="android.permission.SEND_SMS" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
      <uses-permission android:name="android.permission.WRITE_SMS" />
      <uses-permission android:name="android.permission.INTERNET" />
    
  • WendyZangWendyZang Member, Xamarin Team Xamurai

    For your question, you could not send the mail with attachment by Plugin.Messaging. The error cause by the path. You could try the code below.

    1. Follow the README.MD of Xamarin.Plugins.

    https://github.com/cjlotz/Xamarin.Plugins/blob/master/Messaging/README.md

    Add the following to your AndroidManifest.xml inside the tags (YOUR_APP_PACKAGE_NAME must be set to your app package name):

    <provider android:name="android.support.v4.content.FileProvider" 
          android:authorities="YOUR_APP_PACKAGE_NAME.fileprovider" 
          android:exported="false" 
          android:grantUriPermissions="true">
    <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
    </provider>
    

    Add a new folder called xml into your Resources folder and add a new XML file called file_paths.xml. Add the following code:

    <?xml version="1.0" encoding="utf-8" ?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
     <external-path name="external_files" path="." />
     <external-path name="external" path="." />
     <external-files-path name="external_files" path="." />
     <cache-path name="cache" path="." />
     <external-cache-path name="external_cache" path="." />
     <files-path name="files" path="." />
    </paths>
    

    I added all the tags. You could get from the link below.
    https://stackoverflow.com/questions/42516126/fileprovider-illegalargumentexception-failed-to-find-configured-root

    1. Here is the code for your reference.

      private void BtnSendMail_Clicked(object sender, EventArgs e)
        {
           var emailTask = CrossMessaging.Current.EmailMessenger; //MessagingPlugin.EmailMessenger;
           if (emailTask.CanSendEmail)
           {
              string folder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData);
              string file = @"Hello.txt";
              string path = System.IO.Path.Combine(folder, file);
      
              var email = new EmailMessageBuilder()
                .To("[email protected]")
                //.Cc("[email protected]")
                //.Bcc(new[] { "[email protected]", "[email protected]" })
                .Subject("Xamarin Messaging Plugin")
                .Body("Hello from your friends at Xamarin!")
                .WithAttachment(path, "text/plain")
                .Build();
      
      
              emailTask.SendEmail(email);
            }
          }
      

    Note: The WithAttachment(string filePath, string contentType) method has two parameters. The filepath I used is in the Android device, you could check it with path in my code. And the contentType you could get from the extention of the file. You could refer to the useful link from StackOverFlow. It include an efficient and deterministic two-way mapping.
    https://stackoverflow.com/questions/1029740/get-mime-type-from-filename-extension

Sign In or Register to comment.