When you read in the emails from the comparison file, instead of storing the contents of each email, you could compute a hash value for each email and store that instead.
Now when you read emails from the other file, you again compute a hash value for each email and search your list of hashes from the previous pass. If the hash is located, you know that the email was present in the first file.
Since hashes tend to be a lot smaller that the original text (SHA-1 hashes are, for example, 140 bytes each) the collection of hashes should easily fit in RAM.
The following example assumes that emails are stored one per line of text.
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
var exclude = new List<byte[]>();
var sha1 = new SHA1CryptoServiceProvider();
// read exclusion emails
using (var sr = new StreamReader("exclude-file")) {
string email;
// assume one email per line of text
while ((email = sr.ReadLine()) != null) {
exclude.Add(sha1.ComputeHash(new MemoryStream(Encoding.UTF8.GetBytes(email))));
}
}
// read emails
using (var sr = new StreamReader("email-file")) {
string email;
// again, assume one email per line of text
while ((email = sr.ReadLine()) != null) {
if (exclude.Contains(sha1.ComputeHash(new MemoryStream(Encoding.UTF8.GetBytes(email))))) {
// exclusion file contains email
} else {
// exclusion file does not contain email
}
}
}