Remove Email Attachments Programmatically in .NET

Introduction

Ever found yourself drowning in email attachments that you didn’t ask for? Or maybe you’re building an email processing system that needs to filter out specific file types before archiving. Whatever your situation, manually removing attachments from dozens (or hundreds) of emails isn’t exactly how you want to spend your afternoon.

Here’s the good news: you can automate the entire process using GroupDocs.Watermark for .NET. While the name suggests it’s just for watermarks, it’s actually a powerful document manipulation library that handles email attachments with ease.

In this guide, you’ll learn how to programmatically remove specific attachments from emails—whether you’re targeting DOCX files, PDFs, or any other file type. We’ll walk through a practical example that filters out DOCX files containing “sample” in their names, but you can easily adapt this approach for your specific needs.

What You’ll Learn

By the end of this tutorial, you’ll be able to:

  • Set up GroupDocs.Watermark for .NET in your project (it takes about 5 minutes)
  • Write code that automatically filters and removes email attachments
  • Handle common edge cases and errors that pop up during email processing
  • Apply this technique to real-world scenarios like compliance workflows and email archiving

Who This Guide Is For

This tutorial is perfect for you if you’re a .NET developer who:

  • Needs to automate email attachment management
  • Works with MSG or EML email files
  • Wants to clean up email archives before storage
  • Is building compliance or data governance tools

You’ll need a basic understanding of C# and file handling, but I’ll explain everything else as we go.

Why Remove Email Attachments Programmatically?

Let’s be honest—manually opening emails one by one to delete attachments is tedious. But beyond just saving time, there are several compelling reasons to automate this process:

Compliance and Data Governance: Maybe you need to strip out sensitive documents before emails hit your archive. Automating attachment removal ensures consistent enforcement of your data policies.

Storage Optimization: Email attachments eat up storage space fast. Removing unnecessary files (like draft versions or temporary documents) before archiving can cut storage costs significantly.

Security Screening: You might want to filter out executable files or macro-enabled documents as part of your security workflow—doing this manually is both time-consuming and error-prone.

Email Migration: When migrating email systems, you might need to exclude large attachments or specific file types to meet the new platform’s requirements.

The bottom line? If you’re processing more than a handful of emails, automation pays for itself quickly.

Prerequisites

Before we dive into the code, make sure you have:

Required Software:

  • Visual Studio 2019 or later (Community Edition works fine)
  • .NET Core 3.1 or .NET 5+ installed
  • GroupDocs.Watermark for .NET library (we’ll install this in the next section)

Knowledge Prerequisites:

  • Familiarity with C# basics (variables, loops, using statements)
  • Understanding of file paths and directory operations
  • Basic knowledge of how email files (.msg or .eml) are structured (helpful but not required)

Optional but Helpful:

  • An email client to create test .msg files
  • Sample emails with various attachment types for testing

Setting Up GroupDocs.Watermark for .NET

Getting GroupDocs.Watermark into your project is straightforward. Here are three ways to do it:

Installation Options

Option 1: .NET CLI (Quickest Method) Open your terminal in your project directory and run:

dotnet add package GroupDocs.Watermark

Option 2: Package Manager Console In Visual Studio, open Tools → NuGet Package Manager → Package Manager Console, then run:

Install-Package GroupDocs.Watermark

Option 3: NuGet Package Manager UI Right-click your project → Manage NuGet Packages → Browse tab → search for “GroupDocs.Watermark” → Install

License Information

GroupDocs.Watermark isn’t free for production use, but they offer several options:

  • Free Trial: Download from the releases page to test features (has evaluation limitations)
  • Temporary License: Get a 30-day full-featured license from here for development
  • Commercial License: Purchase from GroupDocs for production use

For this tutorial, the free trial works fine—you’ll just see an evaluation watermark in processed files.

Quick Setup Verification

Create a new .NET Console Application and add this code to verify everything’s working:

using GroupDocs.Watermark;
using System;

namespace EmailAttachmentDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("GroupDocs.Watermark setup successful!");
            // We'll add our email processing code here
        }
    }
}

If this compiles and runs without errors, you’re all set!

How to Remove Specific Attachments from Emails

Now for the main event. We’re going to build a solution that scans an email, finds attachments matching specific criteria (in this case, DOCX files with “sample” in the name), and removes them automatically.

Understanding the Workflow

Here’s what happens behind the scenes:

  1. Load the email file (MSG or EML format) using GroupDocs.Watermark
  2. Access the email’s content and attachment collection
  3. Loop through attachments in reverse order (important—I’ll explain why)
  4. Check each attachment against your criteria (file type, name, size, etc.)
  5. Remove matching attachments
  6. Save the modified email to a new file

The reverse iteration is crucial because removing items from a collection while iterating forward causes index issues. Trust me, I learned this the hard way!

Step 1: Set Up Your File Paths

First, define where your input email lives and where you want to save the cleaned version:

string documentPath = Path.Combine("YOUR_DOCUMENT_DIRECTORY", "InMessage.msg"); // Replace with your actual file name.
string outputDirectory = "YOUR_OUTPUT_DIRECTORY"; // Ensure this directory exists or create it before running the code.
string outputFileName = Path.Combine(outputDirectory, Path.GetFileName(documentPath));

Pro tip: Use Path.Combine() instead of string concatenation. It handles path separators correctly across Windows and Linux, which matters if you’re deploying to cloud environments.

Step 2: Load the Email with Proper Options

GroupDocs.Watermark needs to know what type of file you’re loading. That’s where EmailLoadOptions comes in:

var loadOptions = new EmailLoadOptions();
using (Watermarker watermarker = new Watermarker(documentPath, loadOptions))
{
    // Further processing will be done here.
}

The using statement ensures proper cleanup of file handles—critical when you’re processing multiple emails in a batch.

Step 3: Access and Filter Attachments

Here’s where the magic happens. We grab the email content, loop through attachments backwards, and remove the ones that match our criteria:

EmailContent content = watermarker.GetContent<EmailContent>();

for (int i = content.Attachments.Count - 1; i >= 0; i--)
{
    EmailAttachment attachment = content.Attachments[i];
    
    // Check if the attachment name contains 'sample' and is of DOCX file type
    if (attachment.Name.Contains("sample") && attachment.GetDocumentInfo().FileType == FileType.DOCX)
    {
        // Remove the attachment from the email
        content.Attachments.RemoveAt(i);
    }
}

Why iterate backwards? When you remove an item from index 3, all items after it shift down. If you’re iterating forward, you’d skip the item that moved into position 3. Reverse iteration avoids this entirely.

Customizing the filter: You can easily modify the condition. Here are some examples:

// Remove all PDF files
if (attachment.GetDocumentInfo().FileType == FileType.PDF)

// Remove files larger than 5MB
if (attachment.Content.Length > 5 * 1024 * 1024)

// Remove files with specific extensions
if (attachment.Name.EndsWith(".exe") || attachment.Name.EndsWith(".dll"))

// Combine multiple criteria
if (attachment.Name.Contains("draft") && 
    attachment.GetDocumentInfo().FileType == FileType.DOCX &&
    attachment.Content.Length > 1024 * 1024)

Step 4: Save the Modified Email

After removing unwanted attachments, save the cleaned email:

watermarker.Save(outputFileName);

That’s it! The modified email is now ready, with the specified attachments removed.

Complete Working Example

Here’s the full code in one place for easy reference:

using GroupDocs.Watermark;
using GroupDocs.Watermark.Options.Email;
using GroupDocs.Watermark.Common;
using System.IO;

string documentPath = Path.Combine("YOUR_DOCUMENT_DIRECTORY", "InMessage.msg");
string outputDirectory = "YOUR_OUTPUT_DIRECTORY";
string outputFileName = Path.Combine(outputDirectory, Path.GetFileName(documentPath));

var loadOptions = new EmailLoadOptions();
using (Watermarker watermarker = new Watermarker(documentPath, loadOptions))
{
    EmailContent content = watermarker.GetContent<EmailContent>();

    for (int i = content.Attachments.Count - 1; i >= 0; i--)
    {
        EmailAttachment attachment = content.Attachments[i];
        
        if (attachment.Name.Contains("sample") && attachment.GetDocumentInfo().FileType == FileType.DOCX)
        {
            content.Attachments.RemoveAt(i);
        }
    }

    watermarker.Save(outputFileName);
}

Common Pitfalls to Avoid

Let me save you some debugging time by highlighting mistakes I’ve seen (and made myself):

Forgetting to Create Output Directories: The code won’t create the output directory for you. Always check if it exists first:

if (!Directory.Exists(outputDirectory))
{
    Directory.CreateDirectory(outputDirectory);
}

Not Handling Null or Empty Attachment Names: Some email clients create attachments without names. Add a null check:

if (!string.IsNullOrEmpty(attachment.Name) && attachment.Name.Contains("sample"))

Case-Sensitive String Comparisons: “Sample.docx” won’t match “sample” if you’re using Contains(). Use case-insensitive comparison:

if (attachment.Name.Contains("sample", StringComparison.OrdinalIgnoreCase))

Processing While Reading: Don’t try to save back to the input file—it’ll be locked. Always use different output paths.

Forgetting to Dispose: Not using using statements can leave file handles open, especially problematic in batch processing scenarios.

When to Use This Approach

This programmatic method shines in several scenarios:

Automated Email Workflows: If you’re building systems that process incoming emails automatically (like ticketing systems or document management platforms), removing specific attachments can be part of your ingestion pipeline.

Email Archiving Projects: Before moving emails to long-term storage, you might want to strip out certain file types to save space or meet retention policies.

Compliance Requirements: Financial services, healthcare, and legal industries often need to remove or redact certain document types before emails are archived or shared.

Migration Projects: When moving between email systems, you might need to filter attachments to meet size limits or file type restrictions.

Security Screening: As part of a security workflow, automatically removing executable files or macro-enabled documents before emails reach user inboxes.

When NOT to use this: If you’re dealing with just a few emails, manual removal might be faster. This approach pays off when you’re processing dozens or thousands of messages.

Practical Applications and Real-World Scenarios

Let’s look at how you might actually use this in production:

Scenario 1: Automated Email Archive Cleanup

You’re archiving customer support emails but want to remove draft documents (they always have “draft” in the filename):

if (attachment.Name.Contains("draft", StringComparison.OrdinalIgnoreCase))
{
    content.Attachments.RemoveAt(i);
}

Scenario 2: Data Privacy Compliance

Before sharing emails with external auditors, you need to strip out all spreadsheets containing financial data:

if ((attachment.GetDocumentInfo().FileType == FileType.XLSX || 
     attachment.GetDocumentInfo().FileType == FileType.XLS) &&
    attachment.Name.Contains("financial", StringComparison.OrdinalIgnoreCase))
{
    content.Attachments.RemoveAt(i);
}

Scenario 3: Bulk Email Migration

You’re migrating to a new email platform that doesn’t support attachments over 10MB:

if (attachment.Content.Length > 10 * 1024 * 1024) // 10MB in bytes
{
    content.Attachments.RemoveAt(i);
}

Integration with Other Systems

This approach works well as part of larger workflows:

  • CRM Integration: Remove attachments before syncing emails to your CRM to avoid storage bloat
  • Document Management: Extract and route specific attachments to document management systems while removing them from emails
  • Email Filtering Rules: Combine with SMTP listeners to process emails in real-time as they arrive

Troubleshooting Guide

Running into issues? Here are solutions to common problems:

Problem: “File not found” error

  • Solution: Verify your documentPath points to an existing file. Use File.Exists(documentPath) to check before processing.

Problem: “Access denied” when saving

  • Solution: Ensure your application has write permissions to the output directory. Also check that you’re not trying to overwrite a read-only file.

Problem: Email loads but shows zero attachments

  • Solution: Your email might be in a different format. Try using different load options or verify the file isn’t corrupted. Open it in Outlook to confirm attachments exist.

Problem: Wrong attachments being removed

  • Solution: Add logging to see what your conditions are actually matching:
Console.WriteLine($"Checking: {attachment.Name}, Type: {attachment.GetDocumentInfo().FileType}");

Problem: Modified email won’t open in Outlook

  • Solution: Ensure you’re saving with the same file extension. Also verify that you haven’t removed required email components.

Problem: License errors or evaluation watermarks

  • Solution: Make sure your license is properly configured. For testing, the evaluation version works but adds watermarks. Get a temporary license for clean output during development.

Performance Considerations

If you’re processing large volumes of emails, keep these performance tips in mind:

Memory Management: The using statement handles this, but if you’re processing thousands of emails, consider processing in batches and explicitly calling GC.Collect() periodically.

Batch Processing Pattern: Instead of processing one email at a time, batch them:

var emailFiles = Directory.GetFiles(inputDirectory, "*.msg");
foreach (var emailFile in emailFiles)
{
    // Process each email
}

Parallel Processing: For large batches, consider using Parallel.ForEach():

Parallel.ForEach(emailFiles, emailFile => 
{
    // Process email (make sure thread-safety is handled)
});

Disk I/O Optimization: If possible, read from and write to the same disk to avoid cross-drive bottlenecks.

Regular Updates: Keep GroupDocs.Watermark updated. New versions often include performance improvements and bug fixes.

Monitoring: For production systems, log processing times and track memory usage to identify bottlenecks early.

Conclusion

You’ve just learned how to automate email attachment management using GroupDocs.Watermark for .NET. While the library’s name suggests it’s just for watermarks, you’ve seen how powerful it is for email document processing.

To recap, you now know how to:

  • Load and manipulate email files programmatically
  • Filter and remove specific attachments based on any criteria you define
  • Handle common edge cases and errors gracefully
  • Apply this technique to real-world business scenarios

Next Steps

Ready to take this further? Here are some ideas:

  1. Extract Before Removing: Modify the code to save attachments to a folder before removing them (useful for archiving)
  2. Email Reporting: Generate a report of what was removed from each email
  3. Web Interface: Build a simple web UI where users can upload emails and specify removal criteria
  4. Scheduled Processing: Create a Windows Service or scheduled task to process emails automatically

Keep Exploring

GroupDocs.Watermark offers much more than attachment management. Check out the documentation to discover features like:

  • Adding watermarks to documents
  • Removing sensitive metadata
  • Batch document processing
  • Working with various document formats

The skills you’ve learned here form a foundation for building robust document processing workflows. Start small, experiment with different scenarios, and gradually build more sophisticated solutions.

Frequently Asked Questions

1. What file formats does GroupDocs.Watermark support for email processing?

GroupDocs.Watermark works with MSG (Microsoft Outlook) and EML (standard email format) files. These cover the vast majority of email formats you’ll encounter. If you have PST files, you’ll need to extract individual emails first.

2. Can I remove all attachments at once instead of filtering specific ones?

Absolutely! Just use content.Attachments.Clear() instead of the conditional removal loop. This wipes out all attachments in one go—useful for creating attachment-free email archives.

3. How do I handle different attachment types beyond DOCX?

The FileType enum includes dozens of types: PDF, XLSX, JPG, ZIP, and more. You can check for any type using attachment.GetDocumentInfo().FileType == FileType.PDF (or whatever type you need). Combine multiple conditions with || (OR) operators.

4. What should I do if an error occurs during processing?

Wrap your code in try-catch blocks for production use:

try
{
    // Your processing code
}
catch (Exception ex)
{
    Console.WriteLine($"Error processing {documentPath}: {ex.Message}");
    // Log error, send alert, etc.
}

Always log errors with enough context to debug later—include the email filename and what operation failed.

5. Is it possible to automate this process across multiple emails?

Yes! Loop through a directory of email files:

var emailFiles = Directory.GetFiles("C:\\Emails", "*.msg");
foreach (var emailFile in emailFiles)
{
    // Process each email using the code from this tutorial
}

For production scenarios, consider adding error handling, progress tracking, and logging for each file processed.

6. Does this work with cloud-based email services like Gmail or Outlook 365?

Not directly—GroupDocs.Watermark works with email files (MSG/EML), not live mailboxes. You’d need to export emails from your cloud service first, then process them. Many email APIs (like Microsoft Graph API) can help with the export step.

7. How do I test this without affecting my real emails?

Create test emails in Outlook with various attachments and export them as MSG files. Or use sample MSG files from GroupDocs’ examples. Always process copies of emails, never the originals, until you’re confident the code works correctly.

8. Can I use this in a web application?

Yes, GroupDocs.Watermark works in ASP.NET Core and other web frameworks. Just handle file uploads, process the email, and return the modified version for download. Be mindful of concurrent usage and licensing requirements for web deployments.

Resources and Further Reading

Documentation:

Downloads and Licensing:

Community Support: