1. Use only the beginning of the document, as that's probably the most important part anyways, and it's fast.
2. Divide the sum of your feature scores by sqrt(n) to give it constant variance, and hopefully keep it comparable with your prior.
3. Split the doc into reasonably sized chunks, and average their scores rather than adding them.
That seems to be a solution devised for news articles, as the standard news writing style involves providing answers to the Five Ws up front on the article.
Stated more formally, your model is b + wᵀx. Generally, b is < 0, and E[wᵀx] > 0. As the document grows, wᵀx tends to dominate b. You'll have bias with length as long as E[wᵀx]≠0 and there aren't any constraints on w that would force this.
Now obviously real world data doesn't obey these assumptions perfectly. But I don't see how violating the independent features assumption would cause the problem you mention. A longer email does mean the word "viagra" is more likely to occur in a normal email just by random chance. But the model takes that into account by recording the frequency of "viagra" in normal emails and seeing if it's consistent with that.
This problem happens because the class you are interested in is more compact than its inverse.
It's also exacerbated by feature selection, as the negative features have smaller weights and thus lower information gain than the positive features.
A basic technique is to normalize each term within a document following the term frequency-inverse document frequency statistic.