No longer CC a user by default
Its annoying to CC a user on every change they make through the web interface, if they performed the change then they know they did it and don't need a carbon-copy cluttering up their inbox. Add a user level preference setting to control whether or not we should CC the user if we are sending an email on their behalf. By default disable it, because this is a common complaint. Bug: issue 311 Change-Id: I431cc0e5df34ef44114bf3e5c92c4f2d5e3f0354 Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
		| @@ -29,6 +29,7 @@ public interface AccountConstants extends Constants { | ||||
|   String contextWholeFile(); | ||||
|   String showSiteHeader(); | ||||
|   String useFlashClipboard(); | ||||
|   String copySelfOnEmails(); | ||||
|   String buttonSaveChanges(); | ||||
|  | ||||
|   String tabPreferences(); | ||||
|   | ||||
| @@ -6,6 +6,7 @@ registeredOn = Registered | ||||
| accountId = Account ID | ||||
| showSiteHeader = Show Site Header | ||||
| useFlashClipboard = Use Flash Clipboard Widget | ||||
| copySelfOnEmails = CC Me On Comments I Write | ||||
| defaultContextFieldLabel = Default Context: | ||||
| maximumPageSizeFieldLabel = Maximum Page Size: | ||||
| contextWholeFile = Whole File | ||||
|   | ||||
| @@ -40,6 +40,7 @@ import com.google.gwtjsonrpc.client.VoidResult; | ||||
| class PreferencePanel extends Composite { | ||||
|   private CheckBox showSiteHeader; | ||||
|   private CheckBox useFlashClipboard; | ||||
|   private CheckBox copySelfOnEmails; | ||||
|   private ListBox defaultContext; | ||||
|   private ListBox maximumPageSize; | ||||
|   private Button save; | ||||
| @@ -66,6 +67,9 @@ class PreferencePanel extends Composite { | ||||
|     useFlashClipboard = new CheckBox(Util.C.useFlashClipboard()); | ||||
|     useFlashClipboard.addClickHandler(onClickSave); | ||||
|  | ||||
|     copySelfOnEmails = new CheckBox(Util.C.copySelfOnEmails()); | ||||
|     copySelfOnEmails.addClickHandler(onClickSave); | ||||
|  | ||||
|     maximumPageSize = new ListBox(); | ||||
|     for (final short v : PAGESIZE_CHOICES) { | ||||
|       maximumPageSize.addItem(Util.M.rowsPerPage(v), String.valueOf(v)); | ||||
| @@ -92,7 +96,7 @@ class PreferencePanel extends Composite { | ||||
|       labelIdx = 0; | ||||
|       fieldIdx = 1; | ||||
|     } | ||||
|     final Grid formGrid = new Grid(4, 2); | ||||
|     final Grid formGrid = new Grid(5, 2); | ||||
|  | ||||
|     int row = 0; | ||||
|     formGrid.setText(row, labelIdx, ""); | ||||
| @@ -103,6 +107,10 @@ class PreferencePanel extends Composite { | ||||
|     formGrid.setWidget(row, fieldIdx, useFlashClipboard); | ||||
|     row++; | ||||
|  | ||||
|     formGrid.setText(row, labelIdx, ""); | ||||
|     formGrid.setWidget(row, fieldIdx, copySelfOnEmails); | ||||
|     row++; | ||||
|  | ||||
|     formGrid.setText(row, labelIdx, Util.C.maximumPageSizeFieldLabel()); | ||||
|     formGrid.setWidget(row, fieldIdx, maximumPageSize); | ||||
|     row++; | ||||
| @@ -140,6 +148,7 @@ class PreferencePanel extends Composite { | ||||
|   private void enable(final boolean on) { | ||||
|     showSiteHeader.setEnabled(on); | ||||
|     useFlashClipboard.setEnabled(on); | ||||
|     copySelfOnEmails.setEnabled(on); | ||||
|     maximumPageSize.setEnabled(on); | ||||
|     defaultContext.setEnabled(on); | ||||
|   } | ||||
| @@ -147,6 +156,7 @@ class PreferencePanel extends Composite { | ||||
|   private void display(final AccountGeneralPreferences p) { | ||||
|     showSiteHeader.setValue(p.isShowSiteHeader()); | ||||
|     useFlashClipboard.setValue(p.isUseFlashClipboard()); | ||||
|     copySelfOnEmails.setValue(p.isCopySelfOnEmails()); | ||||
|     setListBox(maximumPageSize, DEFAULT_PAGESIZE, p.getMaximumPageSize()); | ||||
|     setListBox(defaultContext, DEFAULT_CONTEXT, p.getDefaultContext()); | ||||
|   } | ||||
| @@ -177,6 +187,7 @@ class PreferencePanel extends Composite { | ||||
|     final AccountGeneralPreferences p = new AccountGeneralPreferences(); | ||||
|     p.setShowSiteHeader(showSiteHeader.getValue()); | ||||
|     p.setUseFlashClipboard(useFlashClipboard.getValue()); | ||||
|     p.setCopySelfOnEmails(copySelfOnEmails.getValue()); | ||||
|     p.setMaximumPageSize(getListBox(maximumPageSize, DEFAULT_PAGESIZE)); | ||||
|     p.setDefaultContext(getListBox(defaultContext, DEFAULT_CONTEXT)); | ||||
|  | ||||
|   | ||||
| @@ -68,6 +68,10 @@ public final class AccountGeneralPreferences { | ||||
|   @Column(id = 6, length = 20, notNull = false) | ||||
|   protected String downloadCommand; | ||||
|  | ||||
|   /** If true we CC the user on their own changes. */ | ||||
|   @Column(id = 7) | ||||
|   protected boolean copySelfOnEmail; | ||||
|  | ||||
|   public AccountGeneralPreferences() { | ||||
|   } | ||||
|  | ||||
| @@ -135,11 +139,20 @@ public final class AccountGeneralPreferences { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public boolean isCopySelfOnEmails() { | ||||
|     return copySelfOnEmail; | ||||
|   } | ||||
|  | ||||
|   public void setCopySelfOnEmails(boolean includeSelfOnEmail) { | ||||
|     copySelfOnEmail = includeSelfOnEmail; | ||||
|   } | ||||
|  | ||||
|   public void resetToDefaults() { | ||||
|     defaultContext = DEFAULT_CONTEXT; | ||||
|     maximumPageSize = DEFAULT_PAGESIZE; | ||||
|     showSiteHeader = true; | ||||
|     useFlashClipboard = true; | ||||
|     copySelfOnEmail = false; | ||||
|     downloadUrl = null; | ||||
|     downloadCommand = null; | ||||
|   } | ||||
|   | ||||
| @@ -19,6 +19,7 @@ import java.io.UnsupportedEncodingException; | ||||
| import java.io.Writer; | ||||
| import java.text.SimpleDateFormat; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
|  | ||||
| @@ -118,6 +119,14 @@ abstract class EmailHeader { | ||||
|       list.add(addr); | ||||
|     } | ||||
|  | ||||
|     void remove(java.lang.String email) { | ||||
|       for (Iterator<Address> i = list.iterator(); i.hasNext();) { | ||||
|         if (i.next().email.equals(email)) { | ||||
|           i.remove(); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     boolean isEmpty() { | ||||
|       return list.isEmpty(); | ||||
|   | ||||
| @@ -32,6 +32,7 @@ import com.google.gerrit.server.account.AccountState; | ||||
| import com.google.gerrit.server.config.CanonicalWebUrl; | ||||
| import com.google.gerrit.server.config.WildProjectName; | ||||
| import com.google.gerrit.server.git.GitRepositoryManager; | ||||
| import com.google.gerrit.server.mail.EmailHeader.AddressList; | ||||
| import com.google.gerrit.server.patch.PatchList; | ||||
| import com.google.gerrit.server.patch.PatchListCache; | ||||
| import com.google.gerrit.server.patch.PatchListEntry; | ||||
| @@ -52,6 +53,7 @@ import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.Date; | ||||
| import java.util.HashSet; | ||||
| import java.util.Iterator; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| @@ -165,12 +167,37 @@ public abstract class OutgoingEmail { | ||||
|     format(); | ||||
|     if (shouldSendMessage()) { | ||||
|       if (fromId != null) { | ||||
|         final Account fromUser = accountCache.get(fromId).getAccount(); | ||||
|  | ||||
|         if (fromUser.getGeneralPreferences().isCopySelfOnEmails()) { | ||||
|           // If we are impersonating a user, make sure they receive a CC of | ||||
|           // this message so they can always review and audit what we sent | ||||
|           // on their behalf to others. | ||||
|           // | ||||
|           add(RecipientType.CC, fromId); | ||||
|  | ||||
|         } else if (rcptTo.remove(fromId)) { | ||||
|           // If they don't want a copy, but we queued one up anyway, | ||||
|           // drop them from the recipient lists. | ||||
|           // | ||||
|           if (rcptTo.isEmpty()) { | ||||
|             return; | ||||
|           } | ||||
|  | ||||
|           final String fromEmail = fromUser.getPreferredEmail(); | ||||
|           for (Iterator<Address> i = smtpRcptTo.iterator(); i.hasNext();) { | ||||
|             if (i.next().email.equals(fromEmail)) { | ||||
|               i.remove(); | ||||
|             } | ||||
|           } | ||||
|           for (EmailHeader hdr : headers.values()) { | ||||
|             if (hdr instanceof AddressList) { | ||||
|               ((AddressList) hdr).remove(fromEmail); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (change != null) { | ||||
|         if (getChangeUrl() != null) { | ||||
|           openFooter(); | ||||
|   | ||||
| @@ -32,7 +32,7 @@ import java.util.List; | ||||
| /** A version of the database schema. */ | ||||
| public abstract class SchemaVersion { | ||||
|   /** The current schema version. */ | ||||
|   private static final Class<? extends SchemaVersion> C = Schema_36.class; | ||||
|   private static final Class<? extends SchemaVersion> C = Schema_37.class; | ||||
|  | ||||
|   public static class Module extends AbstractModule { | ||||
|     @Override | ||||
|   | ||||
| @@ -0,0 +1,25 @@ | ||||
| // Copyright (C) 2010 The Android Open Source Project | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package com.google.gerrit.server.schema; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Provider; | ||||
|  | ||||
| public class Schema_37 extends SchemaVersion { | ||||
|   @Inject | ||||
|   Schema_37(Provider<Schema_36> prior) { | ||||
|     super(prior); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Shawn O. Pearce
					Shawn O. Pearce