Bug 167319: [RFE] "Don't add signature to replies and forwards" option in preferences. r=bienvenu, sr=neil, ui-r=clarkbw
--- a/mail/locales/en-US/chrome/messenger/am-addressing.dtd
+++ b/mail/locales/en-US/chrome/messenger/am-addressing.dtd
@@ -26,8 +26,12 @@
<!ENTITY then.accesskey "T">
<!ENTITY aboveQuote.label "start my reply above the quote">
<!ENTITY belowQuote.label "start my reply below the quote">
<!ENTITY selectAndQuote.label "select the quote">
<!ENTITY place.label "and place my signature">
<!ENTITY place.accesskey "s">
<!ENTITY belowText.label "below the quote (recommended)">
<!ENTITY aboveText.label "below my reply (above the quote)">
+<!ENTITY includeSigOnReply.label "Include signature for replies">
+<!ENTITY includeSigOnReply.accesskey "s">
+<!ENTITY includeSigOnForward.label "Include signature for forwards">
+<!ENTITY includeSigOnForward.accesskey "w">
--- a/mailnews/base/prefs/resources/content/am-addressingOverlay.xul
+++ b/mailnews/base/prefs/resources/content/am-addressingOverlay.xul
@@ -77,29 +77,42 @@
<menulist wsm_persist="true" id="identity.replyOnTop" oncommand="quoteEnabling();"
pref="true" preftype="int" prefattribute="value"
prefstring="mail.identity.%identitykey%.reply_on_top">
<menupopup>
<menuitem value="1" label="&aboveQuote.label;"/>
<menuitem value="0" label="&belowQuote.label;"/>
<menuitem value="2" label="&selectAndQuote.label;"/>
</menupopup>
- </menulist>
+ </menulist>
</hbox>
<hbox class="indent" align="center" id="placeBox">
<label value="&place.label;" accesskey="&place.accesskey;" control="identity.sig_bottom"/>
<menulist wsm_persist="true" id="identity.sig_bottom" genericattr="true"
pref="true" preftype="bool" prefattribute="value"
prefstring="mail.identity.%identitykey%.sig_bottom">
<menupopup>
<menuitem value="true" label="&belowText.label;"/>
<menuitem value="false" label="&aboveText.label;"/>
</menupopup>
</menulist>
</hbox>
+
+ <checkbox id="identity.sig_on_reply" wsm_persist="true"
+ label="&includeSigOnReply.label;"
+ accesskey="&includeSigOnReply.accesskey;"
+ preftype="bool" genericattr="true"
+ prefstring="mail.identity.%identitykey%.sig_on_reply"/>
+
+ <checkbox id="identity.sig_on_fwd" wsm_persist="true"
+ label="&includeSigOnForward.label;"
+ accesskey="&includeSigOnForward.accesskey;"
+ preftype="bool" genericattr="true"
+ prefstring="mail.identity.%identitykey%.sig_on_fwd"/>
+
</groupbox>
<separator class="thin"/>
<groupbox>
<caption label="&addressingGroupTitle.label;"/>
#ifndef MOZ_THUNDERBIRD
<hbox align="center">
--- a/mailnews/base/prefs/resources/content/am-identity-edit.js
+++ b/mailnews/base/prefs/resources/content/am-identity-edit.js
@@ -112,16 +112,18 @@ function initCompositionAndAddressing(id
document.getElementById('identity.overrideGlobal_Pref').value = addressingIdentity.overrideGlobalPref;
#ifndef MOZ_THUNDERBIRD
document.getElementById('identity.autocompleteToMyDomain').checked = addressingIdentity.autocompleteToMyDomain;
#endif
document.getElementById('identity.composeHtml').checked = addressingIdentity.composeHtml;
document.getElementById('identity.autoQuote').checked = addressingIdentity.autoQuote;
document.getElementById('identity.replyOnTop').value = addressingIdentity.replyOnTop;
document.getElementById('identity.sig_bottom').value = addressingIdentity.sigBottom;
+ document.getElementById('identity.sig_on_reply').checked = addressingIdentity.sigOnReply;
+ document.getElementById('identity.sig_on_fwd').checked = addressingIdentity.sigOnForward;
onInitCompositionAndAddressing(); // am-addressing.js method
}
function onOk()
{
if (!validEmailAddress())
return false;
@@ -129,17 +131,17 @@ function onOk()
// if we are adding a new identity, create an identity, set the fields and add it to the
// account.
if (!gIdentity)
{
// ask the account manager to create a new identity for us
var accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"]
.getService(Components.interfaces.nsIMsgAccountManager);
gIdentity = accountManager.createIdentity();
-
+
// copy in the default identity settings so we inherit lots of stuff like the defaul drafts folder, etc.
gIdentity.copy(gAccount.defaultIdentity);
// assume the identity is valid by default?
gIdentity.valid = true;
// add the identity to the account
gAccount.addIdentity(gIdentity);
@@ -157,17 +159,17 @@ function onOk()
return true;
}
// returns false and prompts the user if
// the identity does not have an email address
function validEmailAddress()
{
var emailAddress = document.getElementById('identity.email').value;
-
+
// quickly test for an @ sign to test for an email address. We don't have
// to be anymore precise than that.
if (emailAddress.lastIndexOf("@") < 0)
{
// alert user about an invalid email address
var prefBundle = document.getElementById("bundle_prefs");
@@ -194,17 +196,17 @@ function saveIdentitySettings(identity)
identity.htmlSigFormat = document.getElementById('identity.htmlSigFormat').checked;
identity.attachVCard = document.getElementById('identity.attachVCard').checked;
identity.escapedVCard = document.getElementById('identity.escapedVCard').value;
identity.smtpServerKey = document.getElementById('identity.smtpServerKey').value;
var attachSignaturePath = document.getElementById('identity.signature').value;
identity.signature = null; // this is important so we don't accidentally inherit the default
-
+
if (attachSignaturePath)
{
// convert signature path back into a nsIFile
var sfile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
sfile.initWithPath(attachSignaturePath);
if (sfile.exists())
identity.signature = sfile;
@@ -236,17 +238,19 @@ function saveAddressingAndCompositionSet
identity.directoryServer = document.getElementById('identity.directoryServer').value;
identity.overrideGlobalPref = document.getElementById('identity.overrideGlobal_Pref').value == "true";
#ifndef MOZ_THUNDERBIRD
identity.autocompleteToMyDomain = document.getElementById('identity.autocompleteToMyDomain').checked;
#endif
identity.composeHtml = document.getElementById('identity.composeHtml').checked;
identity.autoQuote = document.getElementById('identity.autoQuote').checked;
identity.replyOnTop = document.getElementById('identity.replyOnTop').value;
- identity.sigBottom = document.getElementById('identity.sig_bottom').value == 'true';
+ identity.sigBottom = document.getElementById('identity.sig_bottom').value == 'true';
+ identity.sigOnReply = document.getElementById('identity.sig_on_reply').checked;
+ identity.sigOnForward = document.getElementById('identity.sig_on_fwd').checked;
}
function selectFile()
{
var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker);
var prefBundle = document.getElementById("bundle_prefs");
@@ -294,17 +298,17 @@ function GetSigFolder()
// Signature textbox is active unless option to select from file is checked.
// If a signature is need to be attached, the associated items which
// displays the absolute path to the signature (in a textbox) and the way
// to select a new signature file (a button) are enabled. Otherwise, they
// are disabled. Check to see if the attachSignature is locked to block
// broadcasting events.
function setupSignatureItems()
-{
+{
var signature = document.getElementById("identity.signature");
var browse = document.getElementById("identity.sigbrowsebutton");
var htmlSigText = document.getElementById("identity.htmlSigText");
var htmlSigFormat = document.getElementById("identity.htmlSigFormat");
var attachSignature = document.getElementById("identity.attachSignature");
var checked = attachSignature.checked;
if (checked)
@@ -343,17 +347,17 @@ function editVCard()
window.openDialog("chrome://messenger/content/addressbook/abNewCardDialog.xul",
"",
"chrome,resizable=no,titlebar,modal",
{escapedVCardStr:escapedVCard.value, okCallback:editVCardCallback,
titleProperty:"editVCardTitle", hideABPicker:true});
}
function getAccountForFolderPickerState()
-{
+{
return gAccount;
}
// when the identity panel is loaded, the smtp-list is created
// and the in prefs.js configured smtp is activated
function loadSMTPServerList()
{
var smtpService = Components.classes["@mozilla.org/messengercompose/smtp;1"].getService(Components.interfaces.nsISmtpService);
--- a/mailnews/base/public/nsIMsgIdentity.idl
+++ b/mailnews/base/public/nsIMsgIdentity.idl
@@ -34,82 +34,120 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsILocalFile.idl"
-/*
- * this interface contains all the personal outgoing mail information
+/**
+ * This interface contains all the personal outgoing mail information
* for a given person.
- * each identity is identified by a key, which is the <id> string in
- * the identity preferences, such as in
- * mail.identity.<id>.replyTo
- *
+ * Each identity is identified by a key, which is the <id> string in
+ * the identity preferences, such as in mail.identity.<id>.replyTo.
*/
-
-
-[scriptable, uuid(592d1e34-acab-4817-8247-0299fdc55204)]
+[scriptable, uuid(2bf98491-1503-4a69-a862-ab6b8e5beb68)]
interface nsIMsgIdentity : nsISupports {
- /* internal preferences ID */
+ /**
+ * Internal preferences ID.
+ */
attribute ACString key;
- /*
- *overriding display name for this identity. if this pref is not set
- * then this will return some composed string from the fullname and email
+ /**
+ * Overriding display name for this identity. If this pref is not set
+ * then this will return some composed string from the fullname and email.
*/
attribute AString identityName;
- /* user's full name, i.e. John Doe */
+ /**
+ * User's full name, i.e. John Doe.
+ */
attribute AString fullName;
- /* user's e-mail address, i.e. john@doe.com */
+ /**
+ * User's e-mail address, i.e. john@doe.com.
+ */
attribute ACString email;
- /* optional replyTo address, i.e. johnNOSPAM@doe.com */
+ /**
+ * Optional replyTo address, i.e. johnNOSPAM@doe.com.
+ */
attribute ACString replyTo;
- /* optional organization */
+ /**
+ * Optional organization.
+ */
attribute AString organization;
- /* should we compose with HTML by default? */
+ /**
+ * Should we compose with HTML by default?
+ */
attribute boolean composeHtml;
- /* should we attach a signature by default? */
+ /**
+ * Should we attach a signature by default?
+ */
attribute boolean attachSignature;
- /* should we attach a vcard by default? */
+ /**
+ * Should we attach a vcard by default?
+ */
attribute boolean attachVCard;
- /* should we automatically quote the original message? */
+ /**
+ * Should we automatically quote the original message?
+ */
attribute boolean autoQuote;
- /* what should our quoting preference be? */
+ /**
+ * What should our quoting preference be?
+ */
attribute long replyOnTop;
- /* what should our signature be at the end of the quoted text when replying above it? */
+ /**
+ * Should our signature be at the end of the quoted text when replying
+ * above it?
+ */
attribute boolean sigBottom;
- /* the current signature if read from file */
+ /**
+ * Include a signature when forwarding a message?
+ */
+ attribute boolean sigOnForward;
+
+ /**
+ * Include a signature when replying to a message?
+ */
+ attribute boolean sigOnReply;
+
+ /**
+ * The current signature file.
+ */
attribute nsILocalFile signature;
+
attribute long signatureDate;
- /* text (format=false) or HTML (format=true) signature if set by preference */
+ /**
+ * Signature text; plain text or HTML depending on htmlSigText.
+ */
attribute AString htmlSigText;
+
+ /**
+ * Is the htmlSigText plain text or HTML?
+ */
attribute boolean htmlSigFormat;
attribute ACString escapedVCard;
attribute boolean doFcc;
/// URI for the fcc (Sent) folder
attribute ACString fccFolder;
attribute boolean fccReplyFollowsParent;
-
+
/**
* @{
* these attributes control whether the special folder pickers for
* fcc, drafts,archives, and templates are set to pick between servers
* (e.g., Sent on accountName) or to pick any folder on any account.
* "0" means choose between servers; "1" means use the full folder picker.
*/
attribute ACString fccFolderPickerMode;
@@ -167,34 +205,34 @@ interface nsIMsgIdentity : nsISupports {
/**
* default request for return receipt option for this identity
* if this is set, the Return Receipt menu item on the compose
* window will be checked
*/
readonly attribute boolean requestReturnReceipt;
readonly attribute long receiptHeaderType;
-
+
/**
* default request for DSN option for this identity
* if this is set, the DSN menu item on the compose
* window will be checked
*/
readonly attribute boolean requestDSN;
/* copy the attributes of the identity we pass in */
void copy(in nsIMsgIdentity identity);
/**
* these generic getter / setters, useful for extending mailnews
* note, these attributes persist across sessions
*/
AString getUnicharAttribute(in string name);
void setUnicharAttribute(in string name, in AString value);
-
+
ACString getCharAttribute(in string name);
void setCharAttribute(in string name, in ACString value);
boolean getBoolAttribute(in string name);
void setBoolAttribute(in string name, in boolean value);
long getIntAttribute(in string name);
void setIntAttribute(in string name, in long value);
--- a/mailnews/base/util/nsMsgIdentity.cpp
+++ b/mailnews/base/util/nsMsgIdentity.cpp
@@ -175,16 +175,18 @@ NS_IMPL_IDPREF_BOOL(ComposeHtml, "compos
NS_IMPL_IDPREF_BOOL(AttachVCard, "attach_vcard")
NS_IMPL_IDPREF_BOOL(AttachSignature, "attach_signature")
NS_IMPL_IDPREF_WSTR(HtmlSigText, "htmlSigText")
NS_IMPL_IDPREF_BOOL(HtmlSigFormat, "htmlSigFormat")
NS_IMPL_IDPREF_BOOL(AutoQuote, "auto_quote")
NS_IMPL_IDPREF_INT(ReplyOnTop, "reply_on_top")
NS_IMPL_IDPREF_BOOL(SigBottom, "sig_bottom")
+NS_IMPL_IDPREF_BOOL(SigOnForward, "sig_on_fwd")
+NS_IMPL_IDPREF_BOOL(SigOnReply, "sig_on_reply")
NS_IMPL_IDPREF_INT(SignatureDate,"sig_date")
NS_IMPL_IDPREF_BOOL(DoFcc, "fcc")
NS_IMPL_FOLDERPREF_STR(FccFolder, "fcc_folder", "Sent", nsMsgFolderFlags::SentMail)
NS_IMPL_IDPREF_STR(FccFolderPickerMode, "fcc_folder_picker_mode")
NS_IMPL_IDPREF_BOOL(FccReplyFollowsParent, "fcc_reply_follows_parent")
@@ -563,16 +565,18 @@ nsMsgIdentity::Copy(nsIMsgIdentity *iden
COPY_IDENTITY_STR_VALUE(identity,GetStationeryFolder,SetStationeryFolder)
COPY_IDENTITY_BOOL_VALUE(identity,GetAttachSignature,SetAttachSignature)
COPY_IDENTITY_FILE_VALUE(identity,GetSignature,SetSignature)
COPY_IDENTITY_WSTR_VALUE(identity,GetHtmlSigText,SetHtmlSigText)
COPY_IDENTITY_BOOL_VALUE(identity,GetHtmlSigFormat,SetHtmlSigFormat)
COPY_IDENTITY_BOOL_VALUE(identity,GetAutoQuote,SetAutoQuote)
COPY_IDENTITY_INT_VALUE(identity,GetReplyOnTop,SetReplyOnTop)
COPY_IDENTITY_BOOL_VALUE(identity,GetSigBottom,SetSigBottom)
+ COPY_IDENTITY_BOOL_VALUE(identity,GetSigOnForward,SetSigOnForward)
+ COPY_IDENTITY_BOOL_VALUE(identity,GetSigOnReply,SetSigOnReply)
COPY_IDENTITY_INT_VALUE(identity,GetSignatureDate,SetSignatureDate)
COPY_IDENTITY_BOOL_VALUE(identity,GetAttachVCard,SetAttachVCard)
COPY_IDENTITY_STR_VALUE(identity,GetEscapedVCard,SetEscapedVCard)
COPY_IDENTITY_STR_VALUE(identity,GetSmtpServerKey,SetSmtpServerKey)
return NS_OK;
}
NS_IMETHODIMP
--- a/mailnews/compose/src/nsMsgCompose.cpp
+++ b/mailnews/compose/src/nsMsgCompose.cpp
@@ -578,16 +578,17 @@ nsMsgCompose::ConvertAndLoadComposeWindo
nsCOMPtr<nsIHTMLEditor> htmlEditor (do_QueryInterface(m_editor));
nsCOMPtr<nsIPlaintextEditor> textEditor (do_QueryInterface(m_editor));
nsCOMPtr<nsIEditorMailSupport> mailEditor (do_QueryInterface(m_editor));
m_editor->BeginTransaction();
PRInt32 reply_on_top = 0;
PRBool sig_bottom = PR_TRUE;
m_identity->GetReplyOnTop(&reply_on_top);
m_identity->GetSigBottom(&sig_bottom);
+
PRBool sigOnTop = (reply_on_top == 1 && !sig_bottom);
if (aQuoted)
{
mInsertingQuotedContent = PR_TRUE;
if (!aPrefix.IsEmpty())
{
if (!aHTMLEditor)
aPrefix.AppendLiteral("\n");
@@ -608,17 +609,17 @@ nsMsgCompose::ConvertAndLoadComposeWindo
m_editor->EndOfDocument();
}
mInsertingQuotedContent = PR_FALSE;
(void)TagEmbeddedObjects(mailEditor);
- if (!aSignature.IsEmpty() )
+ if (!aSignature.IsEmpty())
{
//we cannot add it on top earlier, because TagEmbeddedObjects will mark all images in the signature as "moz-do-not-send"
if( sigOnTop )
m_editor->BeginningOfDocument();
if (aHTMLEditor && htmlEditor)
htmlEditor->InsertHTML(aSignature);
else if (textEditor)
@@ -753,16 +754,40 @@ nsMsgCompose::ConvertAndLoadComposeWindo
#ifdef MSGCOMP_TRACE_PERFORMANCE
nsCOMPtr<nsIMsgComposeService> composeService (do_GetService(NS_MSGCOMPOSESERVICE_CONTRACTID));
composeService->TimeStamp("Finished inserting data into the editor. The window is finally ready!", PR_FALSE);
#endif
return NS_OK;
}
+/**
+ * Check the identity pref to include signature on replies and forwards.
+ */
+PRBool nsMsgCompose::CheckIncludeSignaturePrefs(nsIMsgIdentity *identity)
+{
+ PRBool includeSignature = PR_TRUE;
+ switch (mType)
+ {
+ case nsIMsgCompType::ForwardInline:
+ case nsIMsgCompType::ForwardAsAttachment:
+ identity->GetSigOnForward(&includeSignature);
+ break;
+ case nsIMsgCompType::Reply:
+ case nsIMsgCompType::ReplyAll:
+ case nsIMsgCompType::ReplyToList:
+ case nsIMsgCompType::ReplyToGroup:
+ case nsIMsgCompType::ReplyToSender:
+ case nsIMsgCompType::ReplyToSenderAndGroup:
+ identity->GetSigOnReply(&includeSignature);
+ break;
+ }
+ return includeSignature;
+}
+
nsresult
nsMsgCompose::SetQuotingToFollow(PRBool aVal)
{
mQuotingToFollow = aVal;
return NS_OK;
}
NS_IMETHODIMP
@@ -3946,16 +3971,19 @@ nsMsgCompose::ProcessSignature(nsIMsgIde
nsAutoString sigData;
nsAutoString sigOutput;
PRInt32 reply_on_top = 0;
PRBool sig_bottom = PR_TRUE;
nsCOMPtr<nsILocalFile> sigFile;
if (identity)
{
+ if (!CheckIncludeSignaturePrefs(identity))
+ return NS_OK;
+
identity->GetReplyOnTop(&reply_on_top);
identity->GetSigBottom(&sig_bottom);
rv = identity->GetAttachSignature(&useSigFile);
if (NS_SUCCEEDED(rv) && useSigFile)
{
useSigFile = PR_FALSE; // by default, assume no signature file!
rv = identity->GetSignature(getter_AddRefs(sigFile));
@@ -4190,17 +4218,16 @@ nsMsgCompose::BuildBodyMessageAndSignatu
break;
default :
addSignature = PR_FALSE;
break;
}
nsAutoString tSignature;
-
if (addSignature)
ProcessSignature(m_identity, addDashes, &tSignature);
// if type is new, but we have body, this is probably a mapi send, so we need to
// replace '\n' with <br> so that the line breaks won't be lost by html.
// if mailtourl, do the same.
if (m_composeHTML && (mType == nsIMsgCompType::New || mType == nsIMsgCompType::MailToUrl))
body.ReplaceSubstring(NS_LITERAL_STRING("\n").get(), NS_LITERAL_STRING("<br>").get());
@@ -5243,16 +5270,19 @@ nsresult nsMsgCompose::SetSignature(nsIM
}
} while (node != lastNode && tempNode);
m_editor->EndTransaction();
}
}
}
+ if (!CheckIncludeSignaturePrefs(identity))
+ return NS_OK;
+
//Then add the new one if needed
nsAutoString aSignature;
// No delimiter needed if not a compose window
PRBool noDelimiter;
switch (mType)
{
case nsIMsgCompType::New :
--- a/mailnews/compose/src/nsMsgCompose.h
+++ b/mailnews/compose/src/nsMsgCompose.h
@@ -95,24 +95,17 @@ private:
PRInt32 mWhatHolder;
nsresult LoadDataFromFile(nsILocalFile *file,
nsString &sigData,
PRBool aAllowUTF8 = PR_TRUE,
PRBool aAllowUTF16 = PR_TRUE);
-/*
- nsresult GetCompFields(nsMsgCompFields **aCompFields)
- {
- if (aCompFields)
- *aCompFields = m_compFields;
- return NS_OK;
- }
- */
+ PRBool CheckIncludeSignaturePrefs(nsIMsgIdentity *identity);
nsresult GetIdentity(nsIMsgIdentity **aIdentity)
{
*aIdentity = m_identity;
return NS_OK;
}
//m_folderName to store the value of the saved drafts folder.
nsCString m_folderName;
--- a/mailnews/mailnews.js
+++ b/mailnews/mailnews.js
@@ -428,16 +428,18 @@ pref("mail.identity.default.bcc_list", "
pref("mail.identity.default.draft_folder", "mailbox://nobody@Local%20Folders/Drafts");
pref("mail.identity.default.stationery_folder", "mailbox://nobody@Local%20Folders/Templates");
pref("mail.identity.default.directoryServer", "");
pref("mail.identity.default.overrideGlobal_Pref", false);
pref("mail.identity.default.auto_quote", true);
pref("mail.identity.default.reply_on_top", 0); // 0=bottom 1=top 2=select
pref("mail.identity.default.sig_bottom", true); // true=below quoted false=above quoted
+pref("mail.identity.default.sig_on_fwd", false); // Include signature on fwd?
+pref("mail.identity.default.sig_on_reply", true); // Include signature on re?
// default to archives folder on same server.
pref("mail.identity.default.archives_folder_picker_mode", "0");
// Headers to always add to outgoing mail
// examples: "header1,header2"
// pref("mail.identity.id1.headers", "header1");
// user_pref("mail.identity.id1.header.header1", "X-Mozilla-Rocks: True")
--- a/suite/locales/en-US/chrome/mailnews/pref/am-addressing.dtd
+++ b/suite/locales/en-US/chrome/mailnews/pref/am-addressing.dtd
@@ -28,8 +28,12 @@
<!ENTITY then.accesskey "T">
<!ENTITY aboveQuote.label "start my reply above the quote">
<!ENTITY belowQuote.label "start my reply below the quote">
<!ENTITY selectAndQuote.label "select the quote">
<!ENTITY place.label "and place my signature">
<!ENTITY place.accesskey "s">
<!ENTITY belowText.label "below the quote (recommended)">
<!ENTITY aboveText.label "below my reply (above the quote)">
+<!ENTITY includeSigOnReply.label "Include signature for replies">
+<!ENTITY includeSigOnReply.accesskey "s">
+<!ENTITY includeSigOnForward.label "Include signature for forwards">
+<!ENTITY includeSigOnForward.accesskey "w">