Brandy Mail 1.4 +filter patch

The code adds a TO:<player or mail alias> filter. It filters out incoming messages with TO lines exactly matching the filter text. The code also introduces checking for existing filters.

Author: Greg Kempe
Category: Mail Systems
Compatibility: PennMUSH, TinyBit, TinyMUSH, TinyMUX.

Instructions

Copy and paste the below code into a compatible MUSH or MUX.

MUSHCode for Brandy Mail 1.4 +filter patch

#
# +filter Patch for BrandyMail 14
#
# Version 1 (9/7/98)
# Patch coded by Greg Kempe (kempe@iafrica.com)
# BrandyMail coded by Brandy@CrystalMUSH
# Server: TinyMUSH 2.2.3, BrandyMail 14
#
# HOWTO:
# o To apply the patch, change all occurrences of #17 to the dbref of your
# Parent Mail Object, all occurrences of #13 to the dbref of your Mail
# System object, and all occurrences of #22 to the dbref of your help
# object.
#
# o Run the patch through Andrew Molitor's MUSH unformatter and then quote
# it to your MUSH.
#
# NB: If you have added some other patches that affect the attributes listed
# below, I strongly advise against just overwriting them with these
# versions. The modified sections should, instead, be copied across
# manually (they are clearly marked by comments.)
# If you have installed my bug fixes there is no need to re-install them
# as this code contains those fixes too.
#
# DISCLAIMER: I am not liable for any damages to your DB caused by this code.
# It shouldn't, though, do anything funny, so don't worry too much.
# This patch is in no way an official one for BrandyMail and is
# unsupported by Brandy.
# Please contact me with any oddities, so that I can update the
# patch code.
#
# DESCRIPTION:
# The code adds a TO:<player or mail alias> filter.
# It filters out incoming messages with TO lines exactly matching the filter
# text.
# The code also introduces checking for existing filters.
# '+help mail filters' is updated accordingly.
#
# Eg: +add filter to=medics folder=medical_foo
# +add filter to=jasper folder=important
#
# Match examples:
#
# filter message text works?
# ----------------------------------------------------------------
# Jasper Jasper yes
# Jasper Jasper, and Brandy no
# medics (global mail alias) medics (global mail alias) yes
# medics (global mail alias) medics (personal mail alias) no
#
#
# Modified attributes:
# +add filter : setting the filter and error checking (&ADD_FILTER)
# +remove filter : removal of the filter (&REMOVE_FILTER)
# +list filters : displaying the filter (&LIST_FILTERS)
# &GET_INFO_FOR_ONE_MAILBOX
# : display pretty info for the filter
# &OK_TO_DEST_MAILBOX : checks if TO filters exist
# &FOLDER_TO_STORE_INTO: the heart of the TO filter
# &STORE_LETTER : modified to pass the TO line to the above attrib
# &DISPLAY_MAIL_ADMIN : output on filter counts
# &GET_FILTER_COUNT : modified to tally TO filters too
# &HELP_MAIL_FILTERS,
# &HELP_MAIL_FILTERS2 : updated help information
#
# New mailbox attribute:
# TO_FILTER : text|folder~text|folder
#


&ADD_FILTER #13=$+add filter *=* folder*=*: @swi/first [setq(0, get(%vm/mailbox_%#))][setq(1, edit(lcstr(trim(%3)), %b, $))][setq(4, switch(trim(%0),s*, subject,a*, author,t*, to,error))]1 = strmatch(%3, *reject*=*),,or(strmatch(escape(%0), *[*), strmatch(escape(%1), *[*), strmatch(escape(%3), *[*)), {@pemit %# = u(nofunc)},not(strmatch(type(%#), PLAYER)),{@pemit %# = u(not_player)},strmatch(%q4, error),{@pemit %# = You must specify the type of filter: author, subject or to.%b (syntax:%b +add filter author|subject|to=<name, text or alias> folder=<folder name>)},eq(words(%1), 0),{@pemit %# = You must specify [switch(%q4, author, A player name to filter on, to, A player name or mail alias to filter on, Some text to filter based on subject line)].%b (syntax:%b +add filter author|subject|to=<name, text or alias> folder=<folder name>)}, and(strmatch(%q4, author), not(strmatch(type(*%1), PLAYER))),{@pemit %# = Name specified to filter based on author is not an existing player.},and(strmatch(%q4, to),or(gt(words(%1),1),and(not(strmatch(type(*%1), PLAYER)),not(match(u(%vm/global-mail-aliases) [u(%q0/alias-list)], %1))))),{@pemit %# = Text to filter based on to: field must be a player name or mail alias.}, eq(words(%3), 0),{@pemit %# = You must specify a name for the folder.},gt(strlen([setq(2, [setq(3, %3)]filter(check_for_bad_chars, v(bad_chars)))]%q2), 0),{@pemit %# = Invalid character(s) %q2 detected in folder name.},gt(strlen(%3), 16),{@pemit %# = Folder name specified is too long (maximum of 16 characters).},[setq(5, [switch(%q4,author, [num(*%1)],to,u(pretty_dist,switch(isdbref(num(*%1)), 1,, %1),%q0,get(%q0/alias-list),u(%vm/global-mail-aliases),switch(isdbref(num(*%1)), 1, num(*%1))),%1)])]neq(match(get(%q0/%q4_filter), %q5|%q1, ~), 0),{@pemit %# = That filter already exists.},eq(strlen(%q0), 0),{@create %N's Mailbox; @set [setq(2, con(me))]%q2 = quiet; @drain %q2; &debug_mail %q2 = +add filter %0=%1 folder%2=%3; @tel %q2 = %vm; &mailbox_%# %vm = %q2; @tr %vm/add_mailbox = %q2; &owner_dbref %q2 = %#; @startup %q2 = {@drain me; @no me}; @set %q2 = safe; &mail-in-progress %q2 = false; &%q4_filter %q2 = %q5|%q1; &current_folder %q2 = ulocal(get_inbox, %#); @pemit %# = Filter added.; @no %q2},{@wait %q0 = {&debug_mail %q0 = +add filter %0=%1 folder%2=%3; &%q4_filter %q0 = trim([get(%q0/%q4_filter)]~%q5|%q1,,~); @pemit %# = Filter added.; @no %q0}}
&REMOVE_FILTER #13=$+remove filter*: @swi/first [setq(0, get(%vm/mailbox_%#))]1 = strmatch(escape(%0), *[*),{@pemit %# = u(nofunc)},eq(words(%0), 0), {@pemit %# = You must specify which filter to remove.},eq(strlen(%q0), 0), {@pemit %# = You have no filters defined.},or(not(strmatch(trunc(%0), trim(%0))),lt(%0, 1),not(isnum(%0))),{@pemit %# = You must enter a non-zero integer.%b See +list filters for a list of valid numbers.}, {@wait %q0 = {&debug_mail %q0 = +remove filter%0; @swi/first 1 = [setq(1, get(%q0/author_filter))][setq(2, get(%q0/subject_filter))][setq(3, get(%q0/to_filter))]gt(%0, add(words(%q1, ~), words(%q2, ~), words(%q3, ~))), {@pemit %# = Filter specified does not exist.; @no %q0},lte(%0, words(%q1, ~)), {&author_filter %q0 = ldelete(%q1, %0, ~);@pemit %# = Author filter removed.;@no %q0},lte(%0, add(words(%q1, ~), words(%q2, ~))),{&subject_filter %q0 = ldelete(%q2, sub(%0, words(%q1, ~)), ~); @pemit %# = Subject filter removed.; @no %q0}, {&to_filter %q0 = ldelete(%q3, sub(%0, add(words(%q1, ~), words(%q2, ~))), ~);@pemit %# = To filter removed.;@no %q0} }}
&LIST_FILTERS #13=$+list filters: @swi/first [setq(0, get(%vm/mailbox_%#))]strlen(%q0) = 0,{@pemit %# = You have no filters defined.},{@wait [setq(1, get(%q0/author_filter))][setq(2, get(%q0/subject_filter))][setq(3, u(get_format_option, get(%#/mail_config_options)))][setq(4, get(%q0/to_filter))]%q0 = {&debug_mail %q0 = +list filters; @pemit %# = switch(add(words(%q1, ~), words(%q2, ~), words(%q4, ~)), 0, You have no filters defined.,{[switch(%q3, standard, {[u(equal_line)]%r[center(List of Mail Filters, 78)]%r})][space(6)]Type[space(5)]Value[space(41)]Folder%r[u(dash_line)][iter(%q1, %r[rjust(member(%q1, ##, ~), 3)]\\)%b%bauthor%b%b%b[ljust(switch(type(before(##, |)), PLAYER, name(before(##, |)), destroyed player), 46)][secure(after(##, |))][switch(after(##, |), null, {%b\(discard\)},)],~)][iter(%q2, %r[rjust(add(words(%q1, ~), member(%q2, ##, ~)), 3)]\\)%b%bsubject%b%b[ljust(before(##, |), 46)][secure(after(##, |))][switch(after(##, |), null, {%b\(discard\)},)],~)][iter(iter(lnum(words(%q4, ~)), add(##, 1)),%r[rjust(add(words(%q1, ~), words(%q2, ~), ##), 3)]%)%b%bto[space(7)][setq(9,extract(%q4, ##, 1, ~))][ljust(before(edit(%q9, %%, ), |), 46)][secure(after(%q9, |))][switch(after(%q9, |), null, {%b\(discard\)},)])][switch(%q3, standard, {%r[u(equal_line)]})]}); @no %q0}}
&GET_INFO_FOR_ONE_MAILBOX #17 = [setq(0, get(%0/owner_dbref))][setq(1, get(%0/semaphore))][setq(2, get(%0/mail-in-progress))][setq(3, [switch(%q1, -1,, {[switch(strlen(%q1), 0,%bsem 0, %bsem%q1)]})])][ljust(%0, 7)][switch(hasattr(%0, autoforward), 0, %b%b, a%b)][switch(0, strmatch(owner(%0), owner(#15)), {%b-- WARNING -- This mailbox object is not owned by the right player!},strlen(%q2),{%b-- WARNING -- This does not seem to be a valid mailbox.},strmatch(type(%q0), PLAYER), {%b-- INFORMATIVE -- Mailbox for dest'ed player (do a +destroy mailbox for %q0. Caution:%b all mail sent by that player will be removed from the destination mailboxes)},{[ljust(name(%q0), 17)][ljust(%q2%q3, 11)][rjust(add(words(get(%0/author_filter), ~), words(get(%0/subject_filter), ~),words(get(%0/to_filter), ~),), 7)][rjust(words(get(%0/alias-list)), 9)][rjust(words(remove(get(%0/folder-list), null)), 9)][rjust(words(get(%0/out-list)), 6)][rjust(words(u(get_all_in_lists, %0)), 10)]})]
&OK_TO_DEST_MAILBOX #17 =and(eq(words(u(get_all_in_lists, %0)), 0),eq(words(get(%0/out-list)), 0),strmatch(get(%0/mail-in-progress), false),get(%vm/delete_when_empty),lte(get(%0/semaphore), 0),not(hasattr(%0, alias-list)), not(hasattr(%0, author_filter)), not(hasattr(%0, subject_filter)), not(hasattr(%0, to_filter)),not(hasattr(%0, vacation)), not(hasattr(%0, reject_msg)), not(hasattr(%0, filter_reject)), not(hasattr(%0, autoforward)))
&FOLDER_TO_STORE_INTO #17=first([iter(get(%0/subject_filter), switch(strmatch(%2, *[before(##, |)]*), 1, after(##, |)), ~)] [iter(get(%0/author_filter), switch(strmatch(%1, [before(##, |)]), 1, after(##, |)), ~)] [iter(get(%0/to_filter), switch(strmatch(%4, before(##, |)), 1, after(##, |)), ~)] [ulocal(get_inbox, %3)])
&STORE_LETTER #17 = &[setq(0, u(free_num, get(%0/out-list)))]out-%q0-time_sent %0 = time(); &[setq(3, get(%0/owner_dbref))]out-%q0-subject %0 = %1; &out-list %0 = [get(%0/out-list)] %q0; &out-list-current %0 = switch(words(get(%0/out-list)), 1, %q0, get(%0/out-list-current)); &out-%q0-to %0 = %2; &out-%q0-cc %0 = %4; &out-%q0-bcc %0 = %6; &out-%q0-bcc-expanded %0 = %7; &out-%q0-text %0 = %9[switch([setq(4, get(%q3/MAIL_SIG))]strlen(%q4), 0,, %r%q4)]; &out-%q0-replyall_to %0 = setunion(%q3 %3 %5, ); &out-%q0-held %0 = [setq(8, setunion(iter(setunion(%3 %5 %7, ), ulocal(autoforward_test, ##)), ))]%q8; &out-%q0-dist %0 = iter(%q8, ##:); @dolist %q8 = {@swi/first [setq(1, get(%vm/mailbox_##))][setq(9, u(folder_to_store_into, %q1, get(%0/owner_dbref), %1, ##, %2))]1 = and(strmatch(type(##), PLAYER), eq(strlen(%q1), 0)),{@create [name(##)]'s Mailbox; @set [setq(2, con(me))]%q2 = quiet; @drain %q2; &debug_mail %q2 = store_letter; @tel %q2 = %vm; &mailbox_## %vm = %q2; @tr %vm/add_mailbox = %q2; &owner_dbref %q2 = ##; @startup %q2 = {@drain me; @no me}; @set %q2 = safe; &mail-in-progress %q2 = false; &current_folder %q2 = %q9; &folder-list %q2 = %q9; &in-list-%q9 %q2 = 0; &current_letter-%q9 %q2 = 0; &in-0-time_read %q2 = 0; &in-0-flags %q2 = %8; &in-0-note %q2 = ; &in-0-location %q2 = %0 %q0; @edit %0/out-%q0-dist = ##:,##:0; @pemit ## = switch(%1, Personal Note,, {u(delivery_notification, %q3, sign(match(%8, u)),sign(match(%8, p)),sign(match(%8, rr)),sign(match(%8, r)), secure(%q9))}); @no %q2}, strmatch(type(##), PLAYER), {&folder-list %q1 = setunion(%q9 [get(%q1/folder-list)], ); &in-list-%q9 %q1 = [setq(6, u(free_num, u(get_all_in_lists, %q1)))][setq(7, get(%q1/in-list-%q9))]squish(%q7 %q6); &current_letter-%q9 %q1 = switch(words(%q7), 0, %q6, get(%q1/current_letter-%q9)); &in-%q6-time_read %q1 = 0; &in-%q6-flags %q1 = %8; &in-%q6-note %q1 = ; &in-%q6-location %q1 = %0 %q0; @edit %0/out-%q0-dist = ##:,##:%q6; @pemit ## = switch(1, strmatch(%1, Personal Note),, hasattr(%q1, reject_msg),, {u(delivery_notification, %q3, sign(match(%8, u)),sign(match(%8, p)),sign(match(%8, rr)),sign(match(%8, r)), secure(%q9))}); @swi/first 1 = strmatch(%1, On Vacation),,strmatch(%1, Letter Rejected),,and(strmatch(%q9, null), hasattr(%q1, filter_reject)),{@tr me/remove_letter =%0, %q0, get(%q1/owner_dbref), %q1, %q6, %q9, discard;@tr me/store_letter =%q1,Letter Rejected,name(get(%0/owner_dbref)),get(%0/owner_dbref),,,,,,{Message with subject line "%1" has been rejected by [name(get(%0/owner_dbref))]'s mailbox.%r%r----- Reject Message -----%r%r[get(%q1/filter_reject)]}; @pemit ## = Discarded due to personal mail filter.},strmatch(%q9, null),{@tr me/remove_letter = %0, %q0, get(%q1/owner_dbref), %q1, %q6, %q9,discard; @pemit ## = Discarded due to personal mail filter. },hasattr(%q1, reject_msg), {@tr me/remove_letter = %0, %q0, get(%q1/owner_dbref), %q1, %q6, %q9,reject; @tr me/store_letter = %q1, Letter Rejected, name(get(%0/owner_dbref)), get(%0/owner_dbref), , , , , , {Message with subject line "%1" has been rejected by [name(get(%q1/owner_dbref))]'s mailbox.%r%r----- Reject Message -----%r%r[get(%q1/reject_msg)]}},hasattr(%q1, vacation), {@tr me/store_letter = %q1, On Vacation, name(get(%0/owner_dbref)), get(%0/owner_dbref), , , , , , {Message with subject line "%1" has been stored in [name(get(%q1/owner_dbref))]'s mailbox.%r%r----- Vacation Message -----%r%r[get(%q1/vacation)]}}}, {@pemit get(%0/owner_dbref) = Unable to deliver message.} }
&DISPLAY_MAIL_ADMIN #17 = &folder-list %1 = squish(remove(get(%1/folder-list), null)); @pemit %0 = [setq(0, u(get_format_option, get(%0/mail_config_options)))][setq(1, get(%1/owner_dbref))][setq(2, get(%1/mail-in-progress))][switch(%q0, standard, {[u(equal_line)]%rDetailed status for [name(%q1)]'s mailbox:%r[u(dash_line)]%r})][rjust(Mailbox dbref:, 20)]%b%b%1[switch(strlen(%q2), 0,{%r-- WARNING -- This does not seem to be a valid mailbox.})]%r[rjust(Mail-in-progress:, 20)]%b%b%q2%r[rjust(Received:, 20)]%b%b[words(u(get_all_in_lists, %1))]%r[rjust(Sent:, 20)]%b%b[words(get(%1/out-list))]%r[rjust(Personal aliases:, 20)]%b%b[words(get(%1/alias-list))] [switch(hasattr(%1, alias-list), 0,,([u(list_names, trim(get(%1/alias-list)))]))]%r[rjust(Filters:, 20)]%b%b[ulocal(get_filter_count, %q1)]%r[rjust(Folders:, 20)]%b%b[words(get(%1/folder-list))] [switch(hasattr(%1, folder-list), 0,,{([u(secure_names, trim(get(%1/folder-list)))])})]%r[rjust(Autoforward:, 20)]%b%b[ulocal(get_autoforward_option, %q1)]%r[rjust(Message Timeout:, 20)]%b%b[ulocal(get_timeout_option, %q1)]%r[rjust(Semaphore:, 20)]%b%b[get(%1/semaphore)]%r[rjust(Current Letter:, 20)]%b%b[get(%1/[u(which_current_letter, %1)])]%r[rjust(Current Folder:, 20)]%b%b[secure(get(%1/current_folder))]%r[rjust(Inbox:, 20)]%b%b[secure(ulocal(get_inbox, %q1))]%r[rjust(Vacation:, 20)]%b%b[u(%1/vacation)]%r[rjust(Reject:, 20)]%b%b[u(%1/reject_msg)]%r[rjust(Filter reject:, 20)]%b%b[u(%1/filter_reject)][switch(%q0, standard, {%r[u(equal_line)]})];
&GET_FILTER_COUNT #17 = switch([setq(1, get(%vm/mailbox_%0))]0, strlen(%q1), 0, add(words(get(%q1/author_filter), ~), words(get(%q1/subject_filter), ~),words(get(%q1/to_filter), ~)))
&help_mail_filters #22=%(Page 1 of 2%)%r%rFilters can be used to automatically sort incoming mail into different folders (or automatically delete it if directed to the 'null' folder) based on author, partial match on subject, or exact match on To: header.%r%r%b%b%b%b+add filter author|subject|to=<name, text or alias> folder=<folder name>%r%b%b%b%b+remove filter <number>%r%b%b%b%b+list filters%r%rExamples:%r%r%b%b+add filter author=Brandy folder=null%r%r[space(4)]All incoming mail from Brandy will be automatically deleted. ;)%r%r%b%b+add filter subject=interview folder=interviews%r%r[space(4)]All incoming mail that has the word 'interview' in its subject line will%r[space(4)]be stored in folder 'interviews'.%r%r%b%b+add filter to=applications folder=apps%r%r[space(4)]All incoming mail addressed to the mail alias 'applications' will be%r[space(4)]stored in folder 'apps'%r%rSee also:%b mail filters2, mail folders
&help_mail_filters2 #22=%(Page 2 of 2%)%r%rExtra information for the 'to' filter:%r%rThe filter matches the To: header of a received +mail and is only really applicable to mail aliases. Note that the match must be an exact match.%r%rExamples:%r%rFilter Text[space(24)]To: Header Text[space(21)]Filter?%r[repeat(-,78)]%r[ljust(Jasper, 35)][ljust(Jasper, 36)]Yes%r[ljust(Jasper, 35)][ljust(Jasper and Brandy, 36)]No%r[ljust(medics %(global mail alias%),35)][ljust(medics %(global mail alias%), 36)]Yes%r[ljust(medics %(global mail alias%), 35)][ljust(medics %(global mail alias%) and Jai, 36)]No%r%rThis new filter was coded by Greg Kempe, aka Jasper@TowerMUSH (kempe@iafrica.com)