infobip / infobip-api-csharp-client

Infobip API client library in C#, distributed as a NuGet package.
https://www.infobip.com/docs/api
MIT License
11 stars 17 forks source link

Zip Email attachment - not working - no documentation #34

Closed moisoiu closed 1 week ago

moisoiu commented 6 months ago

Hello,

Description:

We are trying to attach a zip file to the attachment from MemoryStream but for some reason in the e-mail it shows no_file_name_provided. Version: 2.1.3 Environment : Production Reproducing : Attach an zip file via MemoryStream or with System.Net.Mail.Attachment class and it won't add the type and the name.

Good to know: If I download the "no_file_name_provided" and add an extension .zip I can access the resource.

I'm guessing it might be because of the Stream which is to expect System.Io.Stream and maybe it should expect

Example of code

using var attachmentsStream = new MemoryStream(attachment);
System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Zip);
System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(attachmentsStream, ct);
attach.ContentDisposition!.FileName = "file.zip";

infoBipClient.SendMailAsync(
            new MailPropertiesModel
            {
                Receiver = model.Receiver,
                Subject = model.Subject,
                TemplateId = model.TemplateId
            },
            GetPlaceholdersSerialized(model),
            attach.ContentStream);

I've tried even more excentric approach, but still no success.

        var httpResponse = new HttpResponseMessage(HttpStatusCode.OK);
        httpResponse.Content = new StreamContent(attachmentsStream);
        httpResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
        httpResponse.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "download.zip"
        };

        var isSent = await _infoBipClient.SendMailAsync(
            new MailPropertiesModel
            {
                Receiver = model.Receiver,
                Subject = model.Subject,
                TemplateId = model.TemplateId
            },
            GetPlaceholdersSerialized(model),
            await httpResponse.Content.ReadAsStreamAsync());

Could you please help us out what we are missing ?

Later edit:

After digging a bit more in the Source Code I saw this code

private HttpContent PrepareMultipartFormDataContent(RequestOptions options)
        {
            string boundary = "---------" + Guid.NewGuid().ToString().ToUpperInvariant();
            var multipartContent = new MultipartFormDataContent(boundary);
            foreach (var formParameter in options.FormParameters)
                multipartContent.Add(new StringContent(formParameter.Value), formParameter.Key);

            if (options.FileParameters != null && options.FileParameters.Count > 0)
                foreach (var fileParam in options.FileParameters)
                {
                    var fileStreamName = fileParam.Value is FileStream fileStream
                        ? Path.GetFileName(fileStream.Name)
                        : null;
                    var content = new StreamContent(fileParam.Value);
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                    multipartContent.Add(content, fileParam.Key,
                        fileStreamName ?? "no_file_name_provided");
                }

            return multipartContent;
        }

Can there be an extension method for StreamContent ? This would solve all the cases and give the developers flexibility regarding what they want to sent, because I think there are developers that are using In Memory file generation instead of saving on the server.

Thanks, Mircea

moisoiu commented 1 month ago

Hello, any news on this issue?

lvukadinovic-ib commented 1 month ago

Hi @moisoiu, thank you for using our library and for reporting the issue. We're currently in process of releasing the new version of library in order to stay up to date with Infobip APIs. We'll let you know when it is released and we will try to tackle this issue directly afterwards.

Kind regards, Luka

moisoiu commented 1 month ago

Hello @lvukadinovic-ib Thanks for the update would you have a sky estimation by what month we can expect for the new release of the library to appear?

Thanks in advance, Mircea

lvukadinovic-ib commented 1 month ago

Hi @moisoiu , we're aiming to have it released within a few weeks.

Kind regards, Luka

lvukadinovic-ib commented 1 week ago

Hi @moisoiu, we've released a fix for this issue 3.0.1. You can now provide name and extension for attachment files when using streams other than a FileStream. For this a new class was introduced - FileParameter. Given your use case, the following code should do the trick:

MemoryStream yourMemoryStream = ...
FileParameter attachmentFile= new FileParameter("attachment.zip", yourMemoryStream);

emailApi.SendEmail(
    from: "john.smith@somedomain.com",
    to: new List<string> {
        "jane.doe@somecompany.com"
    },
    subject: "Email with an attachment",
    text: "Sent using Infobip API C# Client",
    attachment: new List<FileParameter>
    {
        attachmentFile
    }
);

This should now properly send an email with an "attachment.zip" attachment. I'm marking this as closed. Feel free to reopen the issue if it still persists.