Edgewall Software

Changes between Version 3 and Version 4 of TracDev/NotificationApi


Ignore:
Timestamp:
Dec 6, 2014, 1:24:04 PM (8 years ago)
Author:
Peter Suter
Comment:

Document new notification API, replacing old page entirely

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/NotificationApi

    v3 v4  
    1 = Trac Notification API =
    2 [wiki:TracNotification TracNotification] provides support for event triggered notifications.
    3  ''As of 0.12 only email notification has been implemented. It is used exclusively by the ticket system. This might change in the future, if i.e. the [wiki:TracDev/Proposals/Announcer proposal] for integration of the [th:wiki:AnnouncerPlugin AnnouncerPlugin] infrastructure would be done.''
     1[[PageOutline(2-3)]]
    42
    5 == Existing Interface ==
    6 This is how it's implemented in Trac 0.12. Source: [source:trunk/trac/notification.py trac/notification.py]
     3= Trac Notification API
    74
    8 {{{#!th
    9 type
    10 }}}
    11 {{{#!th
    12 name
    13 }}}
    14 {{{#!th
    15 doc-string/notes
    16 }}}
    17 |----------------
    18 {{{#!td style="background: #efe"
    19 class
    20 }}}
    21 {{{#!td style="background: #efe"
    22 IEmailSender(Interface)
    23 }}}
    24 {{{#!td
    25 Extension point interface for components that allow sending e-mail.
    26 }}}
    27 |----------------
    28 {{{#!td
    29 method
    30 }}}
    31 {{{#!td
    32 send
    33 }}}
    34 {{{#!td
    35 Send message to recipients.
    36 }}}
    37 |----------------
    38 {{{#!td colspan="3"
    39 }}}
    40 |----------------
    41 {{{#!td style="background: #efe"
    42 class
    43 }}}
    44 {{{#!td style="background: #efe"
    45 !NotificationSystem(Component)
    46 }}}
    47 {{{#!td
    48 Name of the component implementing `IEmailSender`.[[BR]]
    49 This component is used by the notification system to send emails. Trac currently provides `SmtpEmailSender` for connecting to an SMTP server, and `SendmailEmailSender` for running a `sendmail`-compatible executable. (''since 0.12'')
    50 {{{#!th
    51 type
    52 }}}
    53 {{{#!th
    54 section
    55 }}}
    56 {{{#!th
    57 option name
    58 }}}
    59 {{{#!th
    60 default value
    61 }}}
    62 {{{#!th
    63 doc-string/notes
    64 }}}
    65 |----------------
    66 {{{#!td
    67 !BoolOption
    68 }}}
    69 {{{#!td
    70 notification
    71 }}}
    72 {{{#!td
    73 smtp_enabled
    74 }}}
    75 {{{#!td
    76 false
    77 }}}
    78 {{{#!td
    79 Enable email notification.
    80 }}}
    81 |----------------
    82 {{{#!td
    83 Option
    84 }}}
    85 {{{#!td
    86 notification
    87 }}}
    88 {{{#!td
    89 smtp_from
    90 }}}
    91 {{{#!td
    92 'trac@localhost'
    93 }}}
    94 {{{#!td
    95 Sender address to use in notification emails.
    96 }}}
    97 |----------------
    98 {{{#!td
    99 Option
    100 }}}
    101 {{{#!td
    102 notification
    103 }}}
    104 {{{#!td
    105 smtp_from_name
    106 }}}
    107 {{{#!td
    108 {{{''}}}
    109 }}}
    110 {{{#!td
    111 Sender name to use in notification emails.
    112 }}}
    113 |----------------
    114 {{{#!td
    115 Option
    116 }}}
    117 {{{#!td
    118 notification
    119 }}}
    120 {{{#!td
    121 smtp_replyto
    122 }}}
    123 {{{#!td
    124 'trac@localhost'
    125 }}}
    126 {{{#!td
    127 Reply-To address to use in notification emails.
    128 }}}
    129 |----------------
    130 {{{#!td
    131 Option
    132 }}}
    133 {{{#!td
    134 notification
    135 }}}
    136 {{{#!td
    137 smtp_always_cc
    138 }}}
    139 {{{#!td
    140 {{{''}}}
    141 }}}
    142 {{{#!td
    143 Email address(es) to always send notifications to, addresses can be seen by all recipients (Cc:).
    144 }}}
    145 |----------------
    146 {{{#!td
    147 Option
    148 }}}
    149 {{{#!td
    150 notification
    151 }}}
    152 {{{#!td
    153 smtp_always_bcc
    154 }}}
    155 {{{#!td
    156 {{{''}}}
    157 }}}
    158 {{{#!td
    159 Email address(es) to always send notifications to, addresses do not appear publicly (Bcc:). (''since 0.10'').
    160 }}}
    161 |----------------
    162 {{{#!td
    163 Option
    164 }}}
    165 {{{#!td
    166 notification
    167 }}}
    168 {{{#!td
    169 smtp_default_domain
    170 }}}
    171 {{{#!td
    172 {{{''}}}
    173 }}}
    174 {{{#!td
    175 Default host/domain to append to address that do not specify one.
    176 }}}
    177 |----------------
    178 {{{#!td
    179 Option
    180 }}}
    181 {{{#!td
    182 notification
    183 }}}
    184 {{{#!td
    185 ignore_domains
    186 }}}
    187 {{{#!td
    188 {{{''}}}
    189 }}}
    190 {{{#!td
    191 Comma-separated list of domains that should not be considered part of email addresses (for usernames with Kerberos domains).
    192 }}}
    193 |----------------
    194 {{{#!td
    195 Option
    196 }}}
    197 {{{#!td
    198 notification
    199 }}}
    200 {{{#!td
    201 admit_domains
    202 }}}
    203 {{{#!td
    204 {{{''}}}
    205 }}}
    206 {{{#!td
    207 Comma-separated list of domains that should be considered as valid for email addresses (such as localdomain).
    208 }}}
    209 |----------------
    210 {{{#!td
    211 Option
    212 }}}
    213 {{{#!td
    214 notification
    215 }}}
    216 {{{#!td
    217 mime_encoding
    218 }}}
    219 {{{#!td
    220 none
    221 }}}
    222 {{{#!td
    223 Specifies the MIME encoding scheme for emails.[[BR]]
    224 Valid options are 'base64' for Base64 encoding, 'qp' for Quoted-Printable, and 'none' for no encoding, in which case mails will be sent as 7bit if the content is all ASCII, or 8bit otherwise. (''since 0.10'')
    225 }}}
    226 |----------------
    227 {{{#!td
    228 !BoolOption
    229 }}}
    230 {{{#!td
    231 notification
    232 }}}
    233 {{{#!td
    234 use_public_cc
    235 }}}
    236 {{{#!td
    237 false
    238 }}}
    239 {{{#!td
    240 Recipients can see email addresses of other CC'ed recipients.[[BR]]
    241 If this option is disabled (the default), recipients are put on BCC. (''since 0.10'')
    242 }}}
    243 |----------------
    244 {{{#!td
    245 !BoolOption
    246 }}}
    247 {{{#!td
    248 notification
    249 }}}
    250 {{{#!td
    251 use_short_addr
    252 }}}
    253 {{{#!td
    254 false
    255 }}}
    256 {{{#!td
    257 Permit email address without a host/domain (i.e. username only).[[BR]]
    258 The SMTP server should accept those addresses, and either append a FQDN or use local delivery. (''since 0.10'')
    259 }}}
    260 |----------------
    261 {{{#!td
    262 Option
    263 }}}
    264 {{{#!td
    265 notification
    266 }}}
    267 {{{#!td
    268 smtp_subject_prefix
    269 }}}
    270 {{{#!td
    271 {{{'__default__'}}}
    272 }}}
    273 {{{#!td
    274 Text to prepend to subject line of notification emails.[[BR]]
    275 If the setting is not defined, then the [$project_name] prefix. If no prefix is desired, then specifying an empty option will disable it. (''since 0.10.1'').
    276 }}}
     5== New API
     6''(since Trac 1.1.3)''
    2777
    278 }}}
    279 |----------------
    280 {{{#!td
    281 method
    282 }}}
    283 {{{#!td
    284 send_email
    285 }}}
    286 {{{#!td
    287 Send message to recipients via e-mail.
    288 }}}
    289 |----------------
    290 {{{#!td colspan="3"
    291 }}}
    292 |----------------
    293 {{{#!td style="background: #efe"
    294 class
    295 }}}
    296 {{{#!td style="background: #efe"
    297 !SmtpEmailSender(Component)
    298 }}}
    299 {{{#!td
    300 '''implements IEmailSender'''[[BR]]
    301 E-mail sender connecting to an SMTP server.
     8The new API keeps the `IEmailSender` extension point and the `NotificationSystem` component almost unchanged from the [#OldAPI old API], but deprecates the entire `Notify` hierarchy.
    3029
    303 {{{#!th
    304 type
    305 }}}
    306 {{{#!th
    307 section
    308 }}}
    309 {{{#!th
    310 option name
    311 }}}
    312 {{{#!th
    313 default value
    314 }}}
    315 {{{#!th
    316 doc-string/notes
    317 }}}
    318 |----------------
    319 {{{#!td
    320 Option
    321 }}}
    322 {{{#!td
    323 notification
    324 }}}
    325 {{{#!td
    326 smtp_server
    327 }}}
    328 {{{#!td
    329 'localhost'
    330 }}}
    331 {{{#!td
    332 SMTP server hostname to use for email notifications.
    333 }}}
    334 |----------------
    335 {{{#!td
    336 !IntOption
    337 }}}
    338 {{{#!td
    339 notification
    340 }}}
    341 {{{#!td
    342 smtp_port
    343 }}}
    344 {{{#!td
    345 25
    346 }}}
    347 {{{#!td
    348 SMTP server port to use for email notification.
    349 }}}
    350 |----------------
    351 {{{#!td
    352 Option
    353 }}}
    354 {{{#!td
    355 notification
    356 }}}
    357 {{{#!td
    358 smtp_user
    359 }}}
    360 {{{#!td
    361 {{{''}}}
    362 }}}
    363 {{{#!td
    364 Username for SMTP server. (''since 0.9'')
    365 }}}
    366 |----------------
    367 {{{#!td
    368 Option
    369 }}}
    370 {{{#!td
    371 notification
    372 }}}
    373 {{{#!td
    374 smtp_password
    375 }}}
    376 {{{#!td
    377 {{{''}}}
    378 }}}
    379 {{{#!td
    380 Password for SMTP server. (''since 0.9'')
    381 }}}
    382 |----------------
    383 {{{#!td
    384 !BoolOption
    385 }}}
    386 {{{#!td
    387 notification
    388 }}}
    389 {{{#!td
    390 use_tls
    391 }}}
    392 {{{#!td
    393 false
    394 }}}
    395 {{{#!td
    396 Use SSL/TLS to send notifications over SMTP. (''since 0.10'')
    397 }}}
     10It is replaced by a new class hierarchy. An instance of such a class contains all known data about an event that requires sending notifications:
     11* [#NotificationEvent] (common properties shared among all events)
     12  * [#TicketChangeEvent] (properties specific to ticket change events)
     13  * [#BatchTicketChangeEvent] (properties specific to ticket batch modification events)
    39814
    399 }}}
    400 |----------------
    401 {{{#!td
    402 method
    403 }}}
    404 {{{#!td
    405 send
    406 }}}
    407 {{{#!td
    408 }}}
    409 |----------------
    410 {{{#!td colspan="3"
    411 }}}
    412 |----------------
    413 {{{#!td style="background: #efe"
    414 class
    415 }}}
    416 {{{#!td style="background: #efe"
    417 !SendmailEmailSender(Component)
    418 }}}
    419 {{{#!td
    420 '''implements IEmailSender'''[[BR]]
    421 E-mail sender using a locally-installed sendmail program.
     15The `NotificationSystem` gains some simple methods to process such events. Also several new extension points are introduced that allow plugins to hook into that processing.
    42216
    423 {{{#!th
    424 type
    425 }}}
    426 {{{#!th
    427 section
    428 }}}
    429 {{{#!th
    430 option name
    431 }}}
    432 {{{#!th
    433 default value
    434 }}}
    435 {{{#!th
    436 doc-string/notes
    437 }}}
    438 |----------------
    439 {{{#!td
    440 Option
    441 }}}
    442 {{{#!td
    443 notification
    444 }}}
    445 {{{#!td
    446 sendmail_path
    447 }}}
    448 {{{#!td
    449 'sendmail'
    450 }}}
    451 {{{#!td
    452 Path to the sendmail executable.[[BR]]
    453 The sendmail program must accept the `-i` and `-f` options. (''since 0.12'')
    454 }}}
     17=== !NotificationEvent
     18Contains the following properties:
     19* `realm`: a string of the affected resource realm (e.g. `'ticket'` or `'wiki'`)
     20* `category`: a string to identify the category of event (e.g. `'created'`, `'changed'` or `'deleted'`)
     21* `target`: the resource [wiki:TracDev/DataModels model] (e.g. an instance of `Ticket` or `WikiPage`) or `None`
     22* `time`: the `datetime` when the event happened
     23* `author`: the [wiki:TracDev/TracSession session id] of the user responsible for the event
    45524
    456 }}}
    457 |----------------
    458 {{{#!td
    459 method
    460 }}}
    461 {{{#!td
    462 send
    463 }}}
    464 {{{#!td
    465 }}}
    466 |----------------
    467 {{{#!td colspan="3"
    468 }}}
    469 |----------------
    470 {{{#!td style="background: #efe"
    471 class
    472 }}}
    473 {{{#!td style="background: #efe"
    474 Notify(object)
    475 }}}
    476 {{{#!td
    477 Generic notification class for Trac.[[BR]]
    478 Subclass this to implement different methods.
    479 }}}
    480 |----------------
    481 {{{#!td
    482 method
    483 }}}
    484 {{{#!td
    485 {{{__init__}}}
    486 }}}
    487 {{{#!td
    488 }}}
    489 |----------------
    490 {{{#!td
    491 method
    492 }}}
    493 {{{#!td
    494 notify
    495 }}}
    496 {{{#!td
    497 }}}
    498 |----------------
    499 {{{#!td
    500 method
    501 }}}
    502 {{{#!td
    503 get_recipients
    504 }}}
    505 {{{#!td
    506 Return a pair of list of subscribers to the resource 'resid'.[[BR]]
    507 First list represents the direct recipients (To:), second list represents the recipients in carbon copy (Cc:).
    508 }}}
    509 |----------------
    510 {{{#!td
    511 method
    512 }}}
    513 {{{#!td
    514 begin_send
    515 }}}
    516 {{{#!td
    517 Prepare to send messages.[[BR]]
    518 Called before sending begins.
    519 }}}
    520 |----------------
    521 {{{#!td
    522 method
    523 }}}
    524 {{{#!td
    525 send
    526 }}}
    527 {{{#!td
    528 Send message to recipients.
    529 }}}
    530 |----------------
    531 {{{#!td
    532 method
    533 }}}
    534 {{{#!td
    535 finish_send
    536 }}}
    537 {{{#!td
    538 Clean up after sending all messages.[[BR]]
    539 Called after sending all messages.
    540 }}}
    541 |----------------
    542 {{{#!td colspan="3"
    543 }}}
    544 |----------------
    545 {{{#!td style="background: #efe"
    546 class
    547 }}}
    548 {{{#!td style="background: #efe"
    549 !NotifyEmail(Notify)
    550 }}}
    551 {{{#!td
    552 Baseclass for notification by email.
    553 }}}
    554 |----------------
    555 {{{#!td
    556 method
    557 }}}
    558 {{{#!td
    559 {{{__init__}}}
    560 }}}
    561 {{{#!td
    562 }}}
    563 |----------------
    564 {{{#!td
    565 method
    566 }}}
    567 {{{#!td
    568 _init_pref_encoding
    569 }}}
    570 {{{#!td
    571 }}}
    572 |----------------
    573 {{{#!td
    574 method
    575 }}}
    576 {{{#!td
    577 notify
    578 }}}
    579 {{{#!td
    580 }}}
    581 |----------------
    582 {{{#!td
    583 method
    584 }}}
    585 {{{#!td
    586 format_header
    587 }}}
    588 {{{#!td
    589 }}}
    590 |----------------
    591 {{{#!td
    592 method
    593 }}}
    594 {{{#!td
    595 add_headers
    596 }}}
    597 {{{#!td
    598 }}}
    599 |----------------
    600 {{{#!td
    601 method
    602 }}}
    603 {{{#!td
    604 get_smtp_address
    605 }}}
    606 {{{#!td
    607 }}}
    608 |----------------
    609 {{{#!td
    610 method
    611 }}}
    612 {{{#!td
    613 encode_header
    614 }}}
    615 {{{#!td
    616 }}}
    617 |----------------
    618 {{{#!td
    619 method
    620 }}}
    621 {{{#!td
    622 send
    623 }}}
    624 {{{#!td
    625 includes methods {{{build_addresses}}} and {{{remove_dup}}}
    626 }}}
     25=== !TicketChangeEvent
     26* `realm` is 'ticket'.
     27* Known values for `category` are `'created'`, `'changed'`, `'attachment added'` and `'attachment deleted'`.
     28* `target` is an instance of `Ticket`.
     29* Additional properties:
     30  * `comment`: a string containing the user's comment (or `None`)
     31  * `changes`: an empty dictionary for now
     32  * `attachment`: `None` for now
    62733
    628 Source: [source:trunk/trac/notification.py trac/notification.py]
     34=== !BatchTicketChangeEvent
     35* `realm` is 'ticket'.
     36* `category` is 'batchmodify'.
     37* `target` is a list of ticket ids(!)
     38* Additional properties:
     39  * `comment`: a string containing the user's comment
     40  * `new_values`: a dictionary with property names as keys and new property values as values.
     41  * `action`: a ticket action controller action
    62942
    630 {{{#!th
    631 type
    632 }}}
    633 {{{#!th
    634 name
    635 }}}
    636 {{{#!th
    637 doc-string/notes
    638 }}}
    639 |----------------
    640 {{{#!td style="background: #efe"
    641 class
    642 }}}
    643 {{{#!td style="background: #efe"
    644 !TicketNotificationSystem(Component)
    645 }}}
    646 {{{#!td
     43== Old API
     44''(since Trac 0.7, deprecated since Trac 1.1.3)''
    64745
    648 {{{#!th
    649 type
    650 }}}
    651 {{{#!th
    652 section
    653 }}}
    654 {{{#!th
    655 option name
    656 }}}
    657 {{{#!th
    658 default value
    659 }}}
    660 {{{#!th
    661 doc-string/notes
    662 }}}
    663 |----------------
    664 {{{#!td
    665 !BoolOption
    666 }}}
    667 {{{#!td
    668 notification
    669 }}}
    670 {{{#!td
    671 always_notify_owner
    672 }}}
    673 {{{#!td
    674 false
    675 }}}
    676 {{{#!td
    677 Always send notifications to the ticket owner (''since 0.9'').
    678 }}}
    679 |----------------
    680 {{{#!td
    681 !BoolOption
    682 }}}
    683 {{{#!td
    684 notification
    685 }}}
    686 {{{#!td
    687 always_notify_reporter
    688 }}}
    689 {{{#!td
    690 false
    691 }}}
    692 {{{#!td
    693 Always send notifications to any address in the ''reporter'' field.
    694 }}}
    695 |----------------
    696 {{{#!td
    697 !BoolOption
    698 }}}
    699 {{{#!td
    700 notification
    701 }}}
    702 {{{#!td
    703 always_notify_updater
    704 }}}
    705 {{{#!td
    706 true
    707 }}}
    708 {{{#!td
    709 Always send notifications to the person who causes the ticket property change and to any previous updater of that ticket.
    710 }}}
    711 |----------------
    712 {{{#!td
    713 Option
    714 }}}
    715 {{{#!td
    716 notification
    717 }}}
    718 {{{#!td
    719 ticket_subject_template
    720 }}}
    721 {{{#!td
    722 '$prefix #$ticket.id: $summary'
    723 }}}
    724 {{{#!td
    725 A Genshi text template snippet used to get the notification subject.[[BR]]
    726 By default, the subject template is `$prefix #$ticket.id: $summary`. `$prefix` being the value of the `smtp_subject_prefix` option. ''(since 0.11)''
    727 }}}
     46The original notification API consisted mainly of a class hierarchy:
     47* `Notify` (abstract base class for notifications based on a plain text template)
     48  * `NotifyEmail` (abstract base class for notifications via plain text email)
     49    * `TicketNotifyEmail` (concrete class for ticket notification emails)
     50    * `BatchTicketNotifyEmail` (concrete class for ticket batch modification notification emails)
    72851
    729 }}}
    730 |----------------
    731 {{{#!td colspan="3"
    732 }}}
    733 |----------------
    734 {{{#!td style="background: #efe"
    735 class
    736 }}}
    737 {{{#!td style="background: #efe"
    738 !TicketNotifyEmail(NotifyEmail)
    739 }}}
    740 {{{#!td
    741 Notification of ticket changes.
    742 }}}
    743 |----------------
    744 {{{#!td
    745 method
    746 }}}
    747 {{{#!td
    748 {{{__init__}}}
    749 }}}
    750 {{{#!td
    751 }}}
    752 |----------------
    753 {{{#!td
    754 method
    755 }}}
    756 {{{#!td
    757 notify
    758 }}}
    759 {{{#!td
    760 Send ticket change notification e-mail (untranslated)
    761 }}}
    762 |----------------
    763 {{{#!td
    764 method
    765 }}}
    766 {{{#!td
    767 _notify
    768 }}}
    769 {{{#!td
    770 }}}
    771 |----------------
    772 {{{#!td
    773 method
    774 }}}
    775 {{{#!td
    776 send
    777 }}}
    778 {{{#!td
    779 }}}
    780 |----------------
    781 {{{#!td
    782 method
    783 }}}
    784 {{{#!td
    785 format_props
    786 }}}
    787 {{{#!td
    788 }}}
    789 |----------------
    790 {{{#!td
    791 method
    792 }}}
    793 {{{#!td
    794 parse_cc
    795 }}}
    796 {{{#!td
    797 }}}
    798 |----------------
    799 {{{#!td
    800 method
    801 }}}
    802 {{{#!td
    803 diff_cc
    804 }}}
    805 {{{#!td
    806 }}}
    807 |----------------
    808 {{{#!td
    809 method
    810 }}}
    811 {{{#!td
    812 format_hdr
    813 }}}
    814 {{{#!td
    815 }}}
    816 |----------------
    817 {{{#!td
    818 method
    819 }}}
    820 {{{#!td
    821 format_subj
    822 }}}
    823 {{{#!td
    824 }}}
    825 |----------------
    826 {{{#!td
    827 method
    828 }}}
    829 {{{#!td
    830 get_recipients
    831 }}}
    832 {{{#!td
    833 }}}
    834 |----------------
    835 {{{#!td
    836 method
    837 }}}
    838 {{{#!td
    839 get_message_id
    840 }}}
    841 {{{#!td
    842 Generate a predictable, but sufficiently unique message ID.
    843 }}}
    844 |----------------
    845 {{{#!td
    846 method
    847 }}}
    848 {{{#!td
    849 send
    850 }}}
    851 {{{#!td
    852 }}}
     52In any situation that required sending notifications, a new instance of such a class was created, invoked once, and discarded. When invoked the object was responsible for finding the recipients, formatting the message and sending the email, all according to various configuration options.
    85353
    854 == Related information ==
    855 Trac plugins using '''!NotifyEmail''' (as of 25-Jul-2010)
    856  * [th:wiki:AccountManagerPlugin AccountManagerPlugin]
    857  * [th:wiki:DiscussionPlugin DiscussionPlugin]
    858  * ''[th:source:tracblplugin TracBLPlugin] looks unmaintained'', no wiki page
    859  * [th:wiki:ExoWebCodeReviewPlugin ExoWebCodeReviewPlugin]
    860  * [th:wiki:FullBlogNotificationPlugin]
    861  * [th:wiki:PrivateCommentPlugin PrivateCommentPlugin]
    862  * [th:wiki:WikiNotificationPlugin WikiNotificationPlugin]
     54This API turned out to be too inflexible. There are too few extension points that would allow plugins to hook into this process. New subclasses could be defined to handle new situations, but existing code would still explicitly use the original `TicketNotifyEmail`. Strong inter-dependencies between the multiple levels of inheritance also make overriding certain things unexpectedly difficult.
    86355
    864 Trac plugins using '''!TicketNotifyEmail''' (as of 25-Jul-2010)
    865  * [th:wiki:AutoTracPlugin AutoTracPlugin]
    866  * [th:wiki:BasicFieldValidationPatch BasicFieldValidationPatch]
    867  * [th:wiki:EmailtoTracScript EmailtoTracScript]
    868  * [th:wiki:FlexibleReporterNotificationPlugin FlexibleReporterNotificationPlugin]
    869  * [th:wiki:GridModifyPlugin GridModifyPlugin]
    870  * [th:wiki:NeverNotifyUpdaterPlugin NeverNotifyUpdaterPlugin]
    871  * [th:wiki:PendingTicketPlugin PendingTicketPlugin]
    872  * [th:wiki:PerforceJobScript PerforceJobScript]
    873  * ''[th:wiki:PublishRevertPlugin PublishRevertPlugin] looks unmaintained''
    874  * [th:wiki:RepositoryHookSystemPlugin RepositoryHookSystemPlugin]
    875  * [th:wiki:RevtreePlugin RevtreePlugin]
    876  * ''[th:wiki:SvnCcHelpersScript SvnCcHelpersScript] unsupported''
    877  * ''[th:wiki:SvnChangeListenerPlugin SvnChangeListenerPlugin] depreciated''
    878  * [th:wiki:TaskListPlugin TaskListPlugin]
    879  * [th:wiki:TimingAndEstimationPlugin TimingAndEstimationPlugin]
    880  * [th:wiki:TracForgePlugin TracForgePlugin]
    881  * [th:wiki:WorkLogPlugin WorkLogPlugin]
    882  * [th:wiki:XmlRpcPlugin XmlRpcPlugin]
    883  * [th:wiki:AwesomeAttachmentsPlugin AwesomeAttachmentsPlugin]
    884  * [th:wiki:GridFlowPlugin GridFlowPlugin]
    885  * [th:wiki:InterTracCommitPatch InterTracCommitPatch]
    886  * [th:wiki:JiraToTracIntegration JiraToTracIntegration]
    887  * [th:wiki:MailToTracPlugin MailToTracPlugin]
    888  * [th:wiki:MilestoneTeamsPlugin MilestoneTeamsPlugin]
    889  * [th:wiki:TicketTeamDispatcherPlugin TicketTeamDispatcherPlugin]
    890  * [th:wiki:TracTicketChangesetsPlugin TracTicketChangesetsPlugin]
     56The only extension point was `IEmailSender`, a low-level backend for sending an already finalized email. ''(Since Trac 0.12)''
     57
     58There was also a `NotificationSystem` component, mainly containing the various configuration option definitions.