diff --git a/trac/ticket/notification.py b/trac/ticket/notification.py
index 7602393..5e1eca0 100644
--- a/trac/ticket/notification.py
+++ b/trac/ticket/notification.py
@@ -22,10 +22,11 @@ from trac.notification import NotifyEmail
 from trac.ticket.api import TicketSystem
 from trac.util import md5
 from trac.util.datefmt import to_utimestamp
-from trac.util.text import CRLF, wrap, obfuscate_email_address
+from trac.util.text import CRLF, wrap, obfuscate_email_address, to_unicode
 from trac.util.translation import deactivate, reactivate
 
 from genshi.template.text import NewTextTemplate
+from unicodedata import east_asian_width
 
 class TicketNotificationSystem(Component):
 
@@ -51,6 +52,15 @@ class TicketNotificationSystem(Component):
         `$prefix` being the value of the `smtp_subject_prefix` option.
         ''(since 0.11)''""")
 
+    ambiguous_char_width = Option('notification', 'ambiguous_char_width',
+                                  'single',
+        """Which width of ambiguous characters (e.g. 'single' or 'double')
+        should be used in the table of notification mail.
+
+        If 'single', the same width as characters in US-ASCII. This is expected
+        by most users. If 'double', twice the width of US-ASCII characters.
+        This is expected by CJK users.""")
+
 
 class TicketNotifyEmail(NotifyEmail):
     """Notification of ticket changes."""
@@ -65,6 +75,10 @@ class TicketNotifyEmail(NotifyEmail):
     def __init__(self, env):
         NotifyEmail.__init__(self, env)
         self.prev_cc = []
+        self.ambiguous_char_width = env.config.get('notification',
+                                                   'ambiguous_char_width',
+                                                   'single')
+        self.text_widths = {}
 
     def notify(self, ticket, newticket=True, modtime=None):
         """Send ticket change notification e-mail (untranslated)"""
@@ -192,9 +206,11 @@ class TicketNotifyEmail(NotifyEmail):
             fval = tkt[fname] or ''
             if fval.find('\n') != -1:
                 continue
+            if fname in ['owner', 'reporter']:
+                fval = obfuscate_email_address(fval)
             idx = 2 * (i % 2)
-            width[idx] = max(len(f['label']), width[idx])
-            width[idx + 1] = max(len(fval), width[idx + 1])
+            width[idx] = max(self.get_text_width(f['label']), width[idx])
+            width[idx + 1] = max(self.get_text_width(fval), width[idx + 1])
             i += 1
         width_l = width[0] + width[1] + 5
         width_r = width[2] + width[3] + 5
@@ -231,20 +247,22 @@ class TicketNotifyEmail(NotifyEmail):
                 str_tmp = u'%s:  %s' % (f['label'], unicode(fval))
                 idx = i % 2
                 cell_tmp[idx] += wrap(str_tmp, width_lr[idx] - 2 + 2 * idx,
-                                      (width[2 * idx] - len(f['label'])
+                                      (width[2 * idx]
+                                       - self.get_text_width(f['label'])
                                        + 2 * idx) * ' ',
                                       2 * ' ', CRLF)
                 cell_tmp[idx] += CRLF
                 i += 1
         cell_l = cell_tmp[0].splitlines()
         cell_r = cell_tmp[1].splitlines()
-        format = u'%%-%is|%%s%%s' % width_l
         for i in range(max(len(cell_l), len(cell_r))):
             if i >= len(cell_l):
                 cell_l.append(width_l * ' ')
             elif i >= len(cell_r):
                 cell_r.append('')
-            txt += format % (cell_l[i], cell_r[i], CRLF)
+            fmt_width = width_l - self.get_text_width(cell_l[i]) \
+                        + len(cell_l[i])
+            txt += u'%-*s|%s%s' % (fmt_width, cell_l[i], cell_r[i], CRLF)
         if big:
             txt += sep
             for name, value in big:
@@ -364,3 +382,27 @@ class TicketNotifyEmail(NotifyEmail):
             hdrs['References'] = msgid
         NotifyEmail.send(self, torcpts, ccrcpts, hdrs)
 
+    def get_text_width(self, text):
+        if self.ambiguous_char_width == 'double':
+            ambiwidth = 2
+        else:
+            ambiwidth = 1
+
+        if not isinstance(text, unicode):
+            text = to_unicode(text)
+
+        if text in self.text_widths:
+            return self.text_widths[text]
+
+        width = 0
+        for ch in text:
+            eaw = east_asian_width(ch)
+            if eaw == 'W' or eaw == 'F':
+                width += 2
+            elif eaw == 'A':
+                width += ambiwidth
+            else:
+                width += 1
+        self.text_widths[text] = width
+        return width
+

