Making an email text-parser generic using PredicateBuilder
First of all, you have one too many parentheses and are missing some variable declarations, so let's fix that up.

var emailText = "";
foreach (List&lt;string&gt; list in groups)
{
    IEnumerable&lt;string&gt; lines3 = list.Where(line =&gt; !line.StartsWith("Cc:", StringComparison.OrdinalIgnoreCase));
    lines3 = lines3.Where(line =&gt; !line.StartsWith("To:", StringComparison.OrdinalIgnoreCase));

    var result = lines3.Select((r, i) =&gt; new { line = r, index = i })
                    .Where(r =&gt;
                        r.line.StartsWith("Regards", StringComparison.OrdinalIgnoreCase)
                        || r.line.StartsWith("Thanks", StringComparison.OrdinalIgnoreCase)
                        || r.line.ToLower().Contains("please do not forward")
                        )
                        .Select(r =&gt; new { LineNo = r.index }).OrderBy(r =&gt; r.LineNo);

    foreach (var item in result)
    {
        var lineNumber = item.LineNo;
        if (lineNumber &gt; 0)
            emailText += String.Join(System.Environment.NewLine, lines3.Take(lineNumber - 1));
        else
            emailText += String.Join(System.Environment.NewLine, lines3);
        break;
    }
}


Now let's run this on

var groups = new List&lt;List&lt;string&gt;&gt;
{
    new List&lt;string&gt; { "Hello", "To: me", "Message body", "Regards", "me" }
};


From your problem description, I would expect the output to be Hello\nMessage body, but it's just Hello. So I'm going to assume the problem description is correct and the code is wrong.

Here are some other notes:


lines3 is not a good variable name.
If you find yourself concatenating a lot of strings, see if you can use a StringBuilder instead.
OrderBy line number is redundant, as the lines are already ordered by line number.


Let's start with a skeleton of what we want the code to look like:

var result = new StringBuilder();
foreach (List&lt;string&gt; email in emails)
{
    // TODO: Remove "to" and "cc" lines.
    // TODO: Remove everything after first "thanks", "regards", etc.
    result.Append(string.Join(Environment.NewLine, ???));
}


Let's handle the easy part first.

private static bool IsDestination(string line)
{
    return line.StartsWith("Cc:", StringComparison.OrdinalIgnoreCase) ||
           line.StartsWith("To:", StringComparison.OrdinalIgnoreCase);
}

var result = new StringBuilder();
foreach (List&lt;string&gt; email in emails)
{
    var filteredEmail = email.Where(line =&gt; !IsDestination(line));
    // TODO: Remove everything after first "thanks", "regards", etc.
    result.Append(string.Join(Environment.NewLine, filteredEmail));
}


Now you want a variable number of phrases to look for, and it seems that some will need to be at the start of the line, while others can be anywhere.

We can write the tests like this

var valedictionTests = new List&lt;Predicate&lt;string&gt;&gt;
{
    line =&gt; line.StartsWith("Regards", StringComparison.OrdinalIgnoreCase),
    line =&gt; line.StartsWith("Thanks", StringComparison.OrdinalIgnoreCase),
    line =&gt; line.IndexOf("Please do not forward", StringComparison.OrdinalIgnoreCase) != -1
};


Then you can add tests like this

valedictionTests.Add(line =&gt; line.StartsWith("Best,", StringComparison.OrdinalIgnoreCase));


And pass them in as a parameter

var result = new StringBuilder();
foreach (List&lt;string&gt; email in emails)
{
    var filteredEmail = email.Where(line =&gt; !IsDestination(line))
        .TakeWhile(line =&gt; !valedictionTests.Any(test =&gt; test(line)));
    result.Append(string.Join(Environment.NewLine, filteredEmail));
}