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:
- Load the email file (MSG or EML format) using GroupDocs.Watermark
- Access the email’s content and attachment collection
- Loop through attachments in reverse order (important—I’ll explain why)
- Check each attachment against your criteria (file type, name, size, etc.)
- Remove matching attachments
- 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
documentPathpoints to an existing file. UseFile.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:
- Extract Before Removing: Modify the code to save attachments to a folder before removing them (useful for archiving)
- Email Reporting: Generate a report of what was removed from each email
- Web Interface: Build a simple web UI where users can upload emails and specify removal criteria
- 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:
- GroupDocs.Watermark Documentation - Comprehensive guides and tutorials
- API Reference - Detailed class and method documentation
Downloads and Licensing:
- Download GroupDocs.Watermark - Latest releases and trial versions
- Temporary License Acquisition - Get 30-day full-featured license
- Purchase Options - Commercial licensing information
Community Support:
- Free Support Forum - Get help from the community and GroupDocs staff