[C#] Send email with attachment, footer & calendar invite (.net)
Sending emails with attachments is a common task in many applications, whether it’s for sharing documents, images, or other files with recipients. In this article, we will explore how to send an email with a file attachment including inserting an image as a footer after the HTML body content, as well as creating a meeting invitation through ‘.ICS’ file attachment using C# code, making use of the built-in .NET framework classes.
The below screenshot shows a sample output generated through C# code which covers all the methods & logic required for sending an email via the SMTP server.

For sending emails, we need:
- Email settings (SMTP server, port number, sender email credentials, recipient email addresses).
- HTML Message/ body content.
- File for Attachment.
- File (Image) for adding logo in the footer section (using LinkedResource & AlternateView Classes).
- Calendar invitations (.ics) file for a meeting request or Calendar invite. (Calendar Appointment As Email Attachment)
Let’s start implementing sending-email functionality in the .Net project using C# code, step-by-step.
Set Up Your Project
First, create a new C# application project in your preferred development environment.
For demo purposes, we will implement this code in the Web API project. The folder and file structure of the solution project is shown below.

Configuring Email Settings
To send an email, you need a valid SMTP (Simple Mail Transfer Protocol) server address, a valid email address for the sender, and the recipient’s email address.
We will use Gmail as SMTP server in our example. Ensure you have access to this basic information before proceeding.
1) smtp server = "smtp.gmail.com";
2) port = 587; // Change if your SMTP server uses a different port
3) sender email e.g., "[email protected]";
4) sender app password e.g., "sender_app_password";
5) recipient email e.g., "[email protected]";
Check this link – How to enable 2-Step verification & set app passwords in your Google account.
If the connection is not established through a secure channel (2-Step Verification) then you will get an authentication failed error message – “The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required.”

Sending Email With Content, Attachments & calendar invite – C# code
Next, we’ll create separate classes and methods that send an email with attachments. In this example, we’ll send a simple text email with a single attachment, footer logo image & meeting request(.ics file) but you can customize it to suit your needs.
Step 1: Create {get set} email property class
Create a property class (MailTemplateProperty.cs) that will serve and get all the essential details for sending an email, such as the SMTP server address, valid email addresses for both the sender and recipient, as well as any attachments such as files, footers, and calendar invite/appointment information.
public class MailTemplateProperty
{
// "SMTP Configuration/Credential"
public string SmtpClientHost { get; set; }
public int SmtpClientPort { get; set; }
public bool SmtpClientEnableSSL { get; set; }
public string CredentialUserName { get; set; }
public string CredentialPass { get; set; }
// "Compose Email"
public string SenderName { get; set; }
public string MailFrom { get; set; }
public string MailTo { get; set; }
public string MailCC { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
/* ===== Optional Setting ===== */
// "File attachments"
public Attachment Attachment { get; set; } = null;
// "Adding logo/image on footer"
public string Footer { get; set; } = null;
// Attach Calendar or meeting properties
public string StartDateTime { get; set; }
public string EndDateTime { get; set; }
public string EventLink { get; set; }
public string EventLocation { get; set; }
public string Attendee { get; set; }
}
Step 2: Create a Class & methods to send mail
It is a good practice to keep all email-sending related functionalities in a separate Class. We create a class called ‘Mail.cs‘ with a function called ‘Send()‘ inside. This function sends an email using the details you provide.
We need to implement all mail-related logic and code implementation in this class, such as:
a) File attachment
Use the Attachment Class from ‘System.Net.Mail’ Namespace. In this example, the code shows that you can pass a file as a parameter either by passing ‘file as MemoryStream with the name’ or mentioning the full physical path & name of the file.
b) Attaching Logo Image as footer note(inline)
We need to use LinkedResource & AlternateView Classes in the mail code to display embedded image(s) in the footer section. How to work with Alternate view – To add an alternate view to a MailMessage object, create an Attachment for the view, and then add it to the collection returned by AlternateViews. Use the Body property to specify the text version and use the AlternateViews collection to specify views with other MIME types.
c) Calendar Appointment As Email Attachment (.ics)
Calendar invitation or ‘. ics’ file is a calendar file saved in a universal calendar format used by several email and calendar programs, including Google Calendar, Microsoft Outlook, and Apple Calendar. It allows adding a calendar link in an email message and users to share the event information on the web and over email which will alert/ remind recipients prior to scheduled meeting time.
d) Common logic
- accepting mail body (plain text or HTML as string) and subject text
- Getting mandatory credential info so that mail can be sent without any failure
All of these functionalities & logic have been incorporated in the code provided below.
Mail.cs – full code – just copy & paste
Ensure you have added the necessary namespace for email functionality.
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Text;
public class Mail
{
// Main method for sending mail
public static bool Send(MailTemplateProperty mailTemplate)
{
string meetingMessageBody = mailTemplate.Body;
mailTemplate.MailFrom = mailTemplate.MailFrom.Trim(',').Trim(';');
if (string.IsNullOrEmpty(mailTemplate.MailFrom))
return false;
try
{
MailMessage mailMessage = new MailMessage
{
From = new MailAddress(mailTemplate.MailFrom,
string.IsNullOrEmpty(mailTemplate.SenderName) ? mailTemplate.MailFrom : mailTemplate.SenderName),
Subject = mailTemplate.Subject,
Body = mailTemplate.Body,
IsBodyHtml = true
};
// Adding File Attachment
if (null != mailTemplate.Attachment)
mailMessage.Attachments.Add(mailTemplate.Attachment);
// Adding To & CC email addresses,
mailTemplate.MailTo = mailTemplate.MailTo.Trim();
mailMessage.To.Add(mailTemplate.MailTo);
if (!string.IsNullOrEmpty(mailTemplate.MailCC) && mailTemplate.MailCC.Length > 0)
mailMessage.CC.Add(mailTemplate.MailCC);
// Adding logo-Image as Footer
if (mailTemplate.Footer != null)
{
LinkedResource res = new LinkedResource(mailTemplate.Footer)
{
ContentId = Guid.NewGuid().ToString()
};
mailTemplate.Body += @"<img src='cid:" + res.ContentId + @"'/>";
AlternateView avHtml = AlternateView.CreateAlternateViewFromString(mailTemplate.Body, null, MediaTypeNames.Text.Html);
avHtml.LinkedResources.Add(res);
mailMessage.AlternateViews.Add(avHtml);
}
// Adding Meeting Request
byte[] byteArray = Encoding.ASCII.GetBytes(MeetingRequestString(mailTemplate.Subject, meetingMessageBody, mailTemplate));
MemoryStream stream = new MemoryStream(byteArray);
Attachment attach = new Attachment(stream, "event-meeting.ics");
mailMessage.Attachments.Add(attach);
// Finally, sending mail via Gmail, SMTP client info with credentials.
SmtpClient smtpClient = new SmtpClient
{
Host = mailTemplate.SmtpClientHost,
Port = mailTemplate.SmtpClientPort,
EnableSsl = mailTemplate.SmtpClientEnableSSL,
Credentials = new NetworkCredential(mailTemplate.CredentialUserName, mailTemplate.CredentialPass),
};
// Send mail by SMTP.
smtpClient.Send(mailMessage);
return true;
}
catch (SmtpFailedRecipientException ex)
{
// LogError(ex.ToString());
return false;
//throw new Exception();
}
catch (SmtpException ex)
{
// LogError(ex.ToString());
return false;
//throw new Exception();
}
catch (Exception ex)
{
// LogError(ex.ToString());
return false;
//throw new Exception();
}
}
// Email Meeting Request- ics meeting/ Calendar invite Code
// Attaching calendar appointment
private static string MeetingRequestString(string subject, string messageBody, MailTemplateProperty mailTemplate, int? eventID = null, bool isCancel = false)
{
StringBuilder str = new StringBuilder();
str.AppendLine("BEGIN:VCALENDAR");
str.AppendLine("PRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN");
str.AppendLine("VERSION:2.0");
str.AppendLine(string.Format("METHOD:{0}", (isCancel ? "CANCEL" : "REQUEST")));
str.AppendLine("METHOD:REQUEST");
str.AppendLine("BEGIN:VEVENT");
str.AppendLine(string.Format("CREATED:{0:yyyyMMddTHHmmssZ}", DateTime.Now.ToUniversalTime()));
// Date format - yyyyMMddTHHmmssZ
str.AppendLine(string.Format("DTSTART:{0}", mailTemplate.StartDateTime));
str.AppendLine(string.Format("DTSTAMP:{0:yyyyMMddTHHmmss}", DateTime.Now.ToUniversalTime()));
str.AppendLine(string.Format("DTEND:{0:}", mailTemplate.EndDateTime));
str.AppendLine(string.Format("LAST-MODIFIED:{0:yyyyMMddTHHmmssZ}", DateTime.Now.ToUniversalTime()));
// web meeting link
str.AppendLine(string.Format("LOCATION: {0}", mailTemplate.EventLink));
//or
//str.AppendLine(string.Format("LOCATION: {0}", mailTemplate.EventLocation));
str.AppendLine("PRIORITY: 5");
str.AppendLine("SEQUENCE: 0");
str.AppendLine(string.Format("UID:{0}", (eventID.HasValue ? "EventId" + eventID : Guid.NewGuid().ToString())));
str.AppendLine(string.Format("DESCRIPTION:{0}", messageBody.Replace("\n", "<br>")));
str.AppendLine(string.Format("X-ALT-DESC;FMTTYPE=text/html:{0}", messageBody.Replace("\n", "<br>")));
str.AppendLine(string.Format("SUMMARY:{0}", subject));
str.AppendLine("STATUS:CONFIRMED");
str.AppendLine(string.Format("ORGANIZER;CN={0}:MAILTO:{1}", mailTemplate.MailFrom, mailTemplate.MailFrom));
str.AppendLine(string.Format("ATTENDEE;CN={0};RSVP=TRUE:mailto:{1}", string.Join(",", mailTemplate.Attendee), string.Join(",", mailTemplate.Attendee)));
str.AppendLine("BEGIN:VALARM");
str.AppendLine("TRIGGER:-PT15M");
str.AppendLine("ACTION:DISPLAY");
str.AppendLine("DESCRIPTION:Reminder");
str.AppendLine("END:VALARM");
str.AppendLine("END:VEVENT");
str.AppendLine("END:VCALENDAR");
return str.ToString();
}
}
Step 3: Call & execute Mail.Send() Method
Common C# code for sending email via SMTP is completed. Now we can call & execute this Mail.Send() method from Controller (SendEmails.cs) or another code page in two steps:
a) Set all Property values
Before calling the Mail.Send() method, set all necessary property values (get all input & assign its values), see the sample below.
MailTemplateProperty mailTemplate = new MailTemplateProperty
{
// "Gmail SMTP Configuration/Credential"
SmtpClientHost = "smtp.gmail.com",
SmtpClientPort = 587,
SmtpClientEnableSSL = true,
CredentialUserName = "[email protected]",
CredentialPass = "google_app_password",
// "Compose Email"
SenderName = "Admin",
MailFrom = "[email protected]",
MailTo = "[email protected]",
MailCC = string.Empty,
Subject = "Next Team Meeting",
Body = "This is a test mail from admin.",
// "File attachments"
//Attachment = new System.Net.Mail.Attachment(mailAttachmentFile.OpenReadStream(), "Meeging.pdf"),
// or
Attachment = new System.Net.Mail.Attachment(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "/Files/Meeting.pdf"),
// "Adding logo/image on footer"
Footer = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "/Images/MailFooterLogo.png",
// Attach Calendar or meeting properties
StartDateTime = DateTime.Now.ToUniversalTime().ToString("yyyyMMddTHHmmssZ"),
EndDateTime = DateTime.Now.AddHours(1).ToUniversalTime().ToString("yyyyMMddTHHmmssZ"),
// MS Teams or Skype or webex meeting link
EventLink = "https://www.webex.com/test-meeting.html",
EventLocation = "Online",
Attendee = "[email protected]"
};
b) Finally, Call Mail.Send() Method
Now, call Mail.Send() method by passing ‘mailTemplate‘ object as a parameter.
Mail.Send(mailTemplate);
That’s it, test the code. if sending mail is successful then the recipient(s) will receive the email in a few seconds. In case of failure, it will return false status as a bool value.
But you can also log an error or throw an exception based on your requirement.
Method 1:
You can get the file attachment from Azure blob storage but in this example, the Meeting.pdf file is attached from the Root folder, see the below screenshot.

Method 2:
You can use IFormFile to receive a file as input from the front-end application and send it as an attachment, please see the implementation in the screenshot.

Download Source Code and try it yourself (open sample project using Visual Studio 2022)

i want this code file
Sure, I will share this code project today.
Post updated, You can download the Source Code and try it.
https://www.codeindotnet.com/send-email-attachment-footer-meeting-invite/#download-source-code
i want this code project please share it ..
Sure, give me some time. Let me test this functionality in a new project, separately, then I will upload it. Update you soon.
I have updated the Post and uploaded the Source Code as well. You can try it.
https://www.codeindotnet.com/send-email-attachment-footer-meeting-invite/#download-source-code