mailman-3.1.1/0000775000175000017500000000000013204154702014250 5ustar maxkingmaxking00000000000000mailman-3.1.1/data/0000775000175000017500000000000013204154701015160 5ustar maxkingmaxking00000000000000mailman-3.1.1/data/mailman-large.jpg0000664000175000017500000001400612632220112020363 0ustar maxkingmaxking00000000000000JFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222]" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?+?QԟNKr%O t/EO4ok *I]TB܀Dz⑮픀q;9eؚθte,vx^VSq؏ΥԊm -i+!!A$sXk]g}1vO Q!kݩ'z¤[ 8R]XӋϧj*)-$RQj}SEsqAo$LeI#vEjR Hsֆe+2O1!橷t3\C#-~O:;0Rs{~O~H=ϓr4R?}w:.XWΜłJOf[J) s4o߾xzUF' *әEef]FGثsdF%h+??EԬ&k{||CMJWDΕ'*s3j*[騦]#Ȑem%vsb˄ $:YSN_&)^~Hb1o8[UY 2ppy8Io{"k2+{xE8-!M <4Z}S[HzҤ:=[)O5<ЯH8*>6Mi;\6\?Z|mDr?оRHV3s$mєVwM $X'snqZoaFҵ*(ץRs9R_jI&m;| |zzZjJT )@ 5wiwqq`'uՖG<.!aȪH|⦋S>n/Fo֦u~ X:}:ǟJ.5);P$prq]MU%F#V̔9l} Ǿ e8DZنUzOnuDg1i#o-F7r{{?*۳̱Z<WdcJÂ/W^ooRăՋ ^Pm.pJ2DH<~N.aW~z_O#FZd);2HXƪ19ElrF3VLv<62*H3q-mXP;J͌`$>yXoNWU31⃫&e@ F20ⲦQٯR44XaF=EU6Imo]>,#ǧ'98ZM+}|ߗf}OKsG#J$|xsX} R -x7r8>}>ZC:$W9vn{1׽hi,ٷ{x$ 2:etDO]2Dhaʳn5K1R 3m'XloGGfKXzӔct׫V||P^i"l:*z`#lgN;? |1{:%l~VǩOj׊ɠbcA|?ֈuiR_jy..Pʱp2zQi/$vwluU𦔡_d'ު\ΚrXԊ`9mMO\N fe+D{ϯ$֮1_QJ[IJTJwіg+3ۚ·#:ΩQt>J{䁑*f][S1D?/tչ:6>1A.k 1P{W̻/nuhfM҇QyvlXjfĭaJ}Z#AOjjۜj?uY[UB REQRMT*KFvA954wŨǔ;CtWGH@e*F=\S6ZPӧz5^8Knqʷ?5oL٬EC$^9}$A{8^6q܃ŵd`@ǘ1wT?}|)ȲƮfVUu*ft=>0xݝ3;jxmeYUJVjͰt۷xޅJSW3>k|w? >9+/a* $lt>Ek(z)G)mΗWx6فiJlV_nu k."!rx?Ϩ*+QH I¾%N>^9#S9 *n\*R3={Iɹ(M;__]Ί6U<2jHf' W=R-433qs|&@hP'=%Uovwj.f3 Cs5=7P,HD)<9BYo,}s[XAX9(Mɕ”[Ofޮ] n\5#\Dh.[Cn޹$O*M$3B;PFʪ6#}N7c8Iⓩi4T0JtQ=޿dPvÆ~th/EODYgW?"]6Eh5;1+:Xe5fK ?NF(2 >toS6AyO)[}_'8GY#qteaYj.]:2D$*y<G犩N4ҚTs8a%smlHYH-^ 檲oBmϿ(畴CxjJRZѝEEs(I ڧLeE? qB?e֯,5xV%p0=sn(u4Q·%WMM! =};5Utܝ2َrѫk/4YL)NTuߚ|1Le*d~HnneM#7 b9gj_Iqgy2p}ԪO(Ζ'^fSs'=Q)d>!!@&~PsVtsT\g8_iQXsOB3 ^ '84dcɴX70, c[^tFc`?}7BZjۡckovMٞ##6GB\_&?2 #~~{ֻ*)8mi SJIzoq6~ ͖R =?pjLJT.Ր"+kc<_ǥJmv4*UyߩZjڕ\Z،aTOrjKU|SK[}94FI*3}jX͹T(۞IY˷7/cO"/ApTF=Mۻv';֤wýSg ׁК. doΒViܹ8&[˾r@ $~+1u)u~vMuM)sOIk(C٨Fp"k:<l-q޴KlQ}kuB3r3O]=#2f rqB<|f14y˰IdUoN:T71V5W998>kb\HAZ%lRRfiINmfзZ#󝊻@&+_`Έ6y }bGɱJT9NSWn::&]`zt =͘׃r;鞞{Mՠ֡-E%B:p3RI j'ЗCb5⥕vӐ4&Id;Jp3O.gCsawK܎? ]N#yrz}CY"8,ĀX`KYDWyV#3j|)YJC+':'6HD?nI]?$U(VTw)>a"Ln 9m sSGeor$q 91SG*'VmYBm hcFQ֖(!F"IjrmtqElOCpP]{ $:$ *m # 2yG'QJ /UhړdtYbrqץS\?Kv3=?_[RpOP&qJ/T=Nn9K"9#8B/99 uj){7ݚm^?q͝/VMjy!{~UnvP 2 ٢ɖ.VNAGQEY˸TS[r&]}hiz,[K܀ ![8#*gpSY#;utVnos8ZV~3\U21K9gw1Bڄ&T }x:(h_\Dȋ֪ұ~#8#E_OE-'Vu>'p)F)#Ur68(isڭzZ*ȼdVݭW<,=̽χnGI␐:_Y[y=awSGcT=.RB.6ۂXɞ2~4i.W48K<r-\|d ܑtFK+ KF'׌TOԽ+:;ǗY5Aȍwl ӯW4.쪣1IPqi>$MsSM.- vpsӧVQxYe3G.h! Y:GZ.e ( ( ( ( ( ( ( ( ( ( dxFFά>RQb=3P)-ٞ2G[cWt=6wh~7m%sd^۶;F23O"VJ?{cӴ!WqZX#C{!N3'Һk{+[PG'XPVӳ :e[hyfEjJᔥ7'vQE2Omailman-3.1.1/data/PythonPowered.png0000664000175000017500000000166112632220112020473 0ustar maxkingmaxking00000000000000PNG  IHDRn,v启gAMA a0PLTEֽBBB999111)))cԯ8tEXtSoftwareXV Version 3.10a Rev: 12/29/94 (PNG patch 1.2).IIDATxV;09f dƴ Ktt3+|Θ++Ɛ"ג}9׵j ss;čÍQ W/͝,ˣ?[80.]j]\pBC~1&) _̓x!k*}\n}d-qp.j6)63_FeIq"sWY~y[nݱ~Rn[y1Wx6n,}ҝpA!Шj dS>\UOI .|iG6Yj*g{ 1 x^mu|{ |34 Nxt__/x]>kP pǡ NV[v:jg'R5M*'$s_B]b_tݠQWuufj ƋߤG/.j'"xY#;vǙbyqxPMʊqk]0N :ǽr8wo@2{t@[t?spƎgwstIME.IIENDB`mailman-3.1.1/data/gnu-head-tiny.jpg0000664000175000017500000000575112632220112020335 0ustar maxkingmaxking00000000000000JFIFZ CREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342 V[ }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz?V 4K !y3܁p+ 4o,2gjT#pA9ǡ85menFk)kV< $wxLXٮȏt;~ FTdVGss"C2=IQ"Dٰs~:擧-VA!,FTgy~(΋,cϙ*·,P|JtOCPF@M`Ade w/ dƃXx(NIW\OYr|Yn.(psFcsqr=LUbOR9*ˁF<%7/o1Rxl; yO4Ǣ|FId.-ܱ$7=N _hڒsfYBj }sV/u/N}K*29xM[N;T7)xFQj>VnD |ǁ s$TiFnפֿ2JH gF,N޽AG;]F~<E!!n9䓵+6vaۖXKȬU8 gګ|\.k#R~;SWcU񥽎<$R̓<6ຜ%+Քaz\׋<[rɞD,nCpdWWQ--M e(AXI s!fK4:4,:O9玦Q#3ș{_ޤp*`HLnF=5 kW p%ܯ,Ai\kź=́YO*pN O W8I,h 1nc'>跺ŤK5 ɕprsF{.cӈ(R6Ȥ2O6ifp$;ќ0s#U4k?t/M=.mmQF8f*~R3\3Ν߀'VHF.bidҳpD)S.h$jhf&"2I\n'aFqtZυ'/Mlݑ$Gv`=  2;q/ 7:i'Ki `Y)KfS[lJRN7A0H+8|O-VݴA#t:6APy>yjpG{51u#W9km 6ο31$p1'e]X`{מG=rcyˬ XՎ8 F+#J]a5ŵ̑I+" ry9BHv^m=ZUS.Byݵu>6_VăO{ %W?fCpE2L>mĿ KW[ȾL,H*HpX Js *Ӭu&hV qm9'ҦK[Yb# {WY?%GJJ4$S\'l {;D-!yF9aܱ Zc9aks[gpB['#!f rvXzT ;9:?ꗍ}$RG ]8e vκ'{gem! xN K.SdhPieU2e,$q x; V:MGOp#db2#r:08>/v H8}xcUvоi$VE.A;rw*ᳳstOyW ,r#,<}+U^H@P Ee\'W77k{Xҟ1[6A+E]#yzU{驩 &(5$Gc',TР(h`$Pq ?Vy1"X=;-fH,ve}U Ӯ3ӞzXHnFaW;/<>n4) \ yN *Ug'=Ma$vp adtt1YigtHHL²bç9 d{e#tQE>՛dV62b$ d[a5XgFDqRp `{fmq#G9f;J 8?q5՞tc)F7m߸s|EQEQ#αc$#)r!]A+yRepe) %yxutgKhWf|r6+wEmailman-3.1.1/data/mm-icon.png0000664000175000017500000000043112632220112017215 0ustar maxkingmaxking00000000000000PNG  IHDRaIDATxR 0 <#6qG8}7q RT|wX3ÖҦDzKavDV>E$'Z{[Zw%9Hkz_BmNd)435E?DCQ154elT;0;<8 ܤ07vs+LZSyt*}{3?0(^IENDB`mailman-3.1.1/data/mailman.jpg0000664000175000017500000000374612632220112017304 0ustar maxkingmaxking00000000000000JFIFXCREATOR: XV Version 3.10a Rev: 12/29/94 (PNG patch 1.2) Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222#n" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?mAG\^#9N.Veن!ҳǪݽ"uyB5uƓ\.Q͵ßx:TzPG]Ukm}uBke sҩ?لSomg;9⧙Vʄbf^롰HO$)x~aX㺶"C $)`X ltm-!>ɸ.G^7}~.DV^:ae%`E0kz%K}B33C(3#Ky4CyY2:sK] Th5yZ]N-XRPIQi|DOH pOOӮ.uq  nnF4^VN4-/- 6f<iY[20Dm08`J</^ēU(' "F`A~3Ji1YRHU9,G)c#Tf.op<ץF3;J/G6TN7.=4rGMW ̶ Fu<$xav]lCTh4aX%AzyMr;?szELp>vd^iͨB0{py#JtѴ mfvFsӧUΚ"b%9>\NK:rvPM;Z+}OZAKszO׊IWEiH:ל) /goQʕnh88=R[va'ٵk,&b.>ڥ7ơ bTĬ3?i_r3N8$:lQ~nrL=򍴶~tD_4p]Ir~ԭ.dc=)-(68'hS=o&lpF9V;soVΏdsI v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'GNUMailmandoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('README', 'GNUMailman.tex', u'GNU Mailman Documentation', u'Barry Warsaw', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('README', 'gnumailman', u'GNU Mailman Documentation', [u'Barry Warsaw'], 1) ] def index_html(): import errno cwd = os.getcwd() try: try: os.makedirs('build/sphinx/html') except OSError as error: if error.errno != errno.EEXIST: raise os.chdir('build/sphinx/html') try: os.symlink('README.html', 'index.html') print 'index.html -> README.html' except OSError as error: if error.errno != errno.EEXIST: raise finally: os.chdir(cwd) import atexit atexit.register(index_html) mailman-3.1.1/copybump.py0000775000175000017500000000534212754530654016504 0ustar maxkingmaxking00000000000000#! /usr/bin/env python3 import os import re import sys import stat import datetime FSF = 'by the Free Software Foundation, Inc.' this_year = datetime.date.today().year pyre_c = re.compile(r'# Copyright \(C\) ((?P\d{4})-)?(?P\d{4})') pyre_n = re.compile(r'# Copyright ((?P\d{4})-)?(?P\d{4})') new_c = '# Copyright (C) {}-{} {}' new_n = '# Copyright {}-{} {}' MODE = (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) if '--noc' in sys.argv: pyre = pyre_n new = new_n sys.argv.remove('--noc') else: pyre = pyre_c new = new_c def do_file(path, owner): permissions = os.stat(path).st_mode & MODE with open(path) as in_file, open(path + '.out', 'w') as out_file: try: for line in in_file: mo_c = pyre_c.match(line) mo_n = pyre_n.match(line) if mo_c is None and mo_n is None: out_file.write(line) continue mo = (mo_n if mo_c is None else mo_c) start = (mo.group('end') if mo.group('start') is None else mo.group('start')) if int(start) == this_year: out_file.write(line) continue print(new.format(start, this_year, owner), file=out_file) print('=>', path) for line in in_file: out_file.write(line) except UnicodeDecodeError: print('Cannot convert path:', path) os.remove(path + '.out') return os.rename(path + '.out', path) os.chmod(path, permissions) def remove(dirs, path): try: dirs.remove(path) except ValueError: pass def do_walk(): try: owner = sys.argv[1] except IndexError: owner = FSF for root, dirs, files in os.walk('.'): if root == '.': remove(dirs, '.git') remove(dirs, '.tox') remove(dirs, 'bin') remove(dirs, 'contrib') remove(dirs, 'develop-eggs') remove(dirs, 'eggs') remove(dirs, 'parts') remove(dirs, 'gnu-COPYING-GPL') remove(dirs, '.installed.cfg') remove(dirs, '.bzrignore') remove(dirs, 'distribute_setup.py') if root == './src': remove(dirs, 'mailman.egg-info') if root == './src/mailman': remove(dirs, 'messages') for file_name in files: if os.path.splitext(file_name)[1] in ('.pyc', '.gz', '.egg'): continue path = os.path.join(root, file_name) if os.path.isfile(path): do_file(path, owner) if __name__ == '__main__': do_walk() mailman-3.1.1/coverage.ini0000664000175000017500000000065713203705633016560 0ustar maxkingmaxking00000000000000[run] branch = true parallel = true omit = setup* */showme.py .tox/*/lib/python3.*/site-packages/* .tox/*/lib/python3.*/site-packages/* */test_*.py /tmp/* /private/var/folders/* */testing/*.py [report] exclude_lines = pragma: nocover pragma: missed raise NotImplementedError raise AssertionError assert\s [paths] source = mailman .tox/*/lib/python3.*/site-packages/mailman mailman-3.1.1/cron/0000775000175000017500000000000013204154701015210 5ustar maxkingmaxking00000000000000mailman-3.1.1/cron/crontab.in.in0000775000175000017500000000202512603721003017574 0ustar maxkingmaxking00000000000000# At 8AM every day, mail reminders to admins as to pending requests. # They are less likely to ignore these reminders if they're mailed # early in the morning, but of course, this is local time... ;) 0 8 * * * @PYTHON@ -S @prefix@/cron/checkdbs # # At 9AM, send notifications to disabled members that are due to be # reminded to re-enable their accounts. 0 9 * * * @PYTHON@ -S @prefix@/cron/disabled # # Noon, mail digests for lists that do periodic as well as threshhold delivery. 0 12 * * * @PYTHON@ -S @prefix@/cron/senddigests # # Every 5 mins, try to gate news to mail. You can comment this one out # if you don't want to allow gating, or don't have any going on right now, # or want to exclusively use a callback strategy instead of polling. 0,5,10,15,20,25,30,35,40,45,50,55 * * * * @PYTHON@ -S @prefix@/cron/gate_news # # At 3:27am every night, regenerate the gzip'd archive file. Only # turn this on if the internal archiver is used and # GZIP_ARCHIVE_TXT_FILES is false in mm_cfg.py 27 3 * * * @PYTHON@ -S @prefix@/cron/nightly_gzip mailman-3.1.1/src/0000775000175000017500000000000013204154701015036 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/0000775000175000017500000000000013204154701016454 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/config/0000775000175000017500000000000013204154701017721 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/config/mailman.cfg0000664000175000017500000000471413066532160022033 0ustar maxkingmaxking00000000000000# Copyright (C) 2008-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . # This is the absolute bare minimum base configuration file. User supplied # configurations are pushed onto this. [paths.local] # Directories as specified in schema.cfg, putting most stuff in # /var/tmp/mailman [paths.dev] # Convenient development layout where everything is put in a directory above # where the mailman.cfg file lives. var_dir: $cfg_file/../.. [paths.here] # Layout where the var directory is put in the current working directory. var_dir: $cwd/var [paths.fhs] # Filesystem Hiearchy Standard 2.3 # http://www.pathname.com/fhs/pub/fhs-2.3.html bin_dir: /sbin var_dir: /var/lib/mailman queue_dir: /var/spool/mailman log_dir: /var/log/mailman lock_dir: /var/lock/mailman etc_dir: /etc ext_dir: /etc/mailman.d pid_file: /var/run/mailman/master.pid [language.en] [runner.archive] class: mailman.runners.archive.ArchiveRunner [runner.bad] class: mailman.runners.fake.BadRunner # The bad runner is just a placeholder for its switchboard. start: no [runner.bounces] class: mailman.runners.bounce.BounceRunner [runner.command] class: mailman.runners.command.CommandRunner [runner.in] class: mailman.runners.incoming.IncomingRunner [runner.lmtp] class: mailman.runners.lmtp.LMTPRunner path: [runner.nntp] class: mailman.runners.nntp.NNTPRunner [runner.out] class: mailman.runners.outgoing.OutgoingRunner [runner.pipeline] class: mailman.runners.pipeline.PipelineRunner [runner.rest] class: mailman.runners.rest.RESTRunner path: [runner.retry] class: mailman.runners.retry.RetryRunner sleep_time: 15m [runner.shunt] class: mailman.runners.fake.ShuntRunner # The shunt runner is just a placeholder for its switchboard. start: no [runner.virgin] class: mailman.runners.virgin.VirginRunner [runner.digest] class: mailman.runners.digest.DigestRunner mailman-3.1.1/src/mailman/config/configure.zcml0000644000175000017500000000743313004252243022574 0ustar maxkingmaxking00000000000000 mailman-3.1.1/src/mailman/config/exim4.cfg0000664000175000017500000000020112632220112021413 0ustar maxkingmaxking00000000000000[exim4] # Additional configuration variables for the Exim MTA, version 4. # Exim doesn't need any additional configuration yet. mailman-3.1.1/src/mailman/config/postfix.cfg0000664000175000017500000000112513142746474022114 0ustar maxkingmaxking00000000000000[postfix] # Additional configuration variables for the postfix MTA. # This variable describe the program to use for regenerating the transport map # db file, from the associated plain text files. The file being updated will # be appended to this string (with a separating space), so it must be # appropriate for os.system(). postmap_command: /usr/sbin/postmap # This variable describes the type of transport maps that will be generated by # mailman to be used with postfix for LMTP transport. By default, it is set to # hash, but mailman also supports `regex` tables. transport_file_type: hash mailman-3.1.1/src/mailman/config/tests/0000775000175000017500000000000013204154701021063 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/config/tests/test_configuration.py0000664000175000017500000001354713066532160025362 0ustar maxkingmaxking00000000000000# Copyright (C) 2012-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the system-wide global configuration.""" import os import unittest from contextlib import ExitStack from mailman.config.config import ( Configuration, external_configuration, load_external) from mailman.interfaces.configuration import ( ConfigurationUpdatedEvent, MissingConfigurationFileError) from mailman.testing.helpers import configuration, event_subscribers from mailman.testing.layers import ConfigLayer from pkg_resources import resource_filename from tempfile import NamedTemporaryFile, TemporaryDirectory from unittest import mock class TestConfiguration(unittest.TestCase): layer = ConfigLayer def test_push_and_pop_trigger_events(self): # Pushing a new configuration onto the stack triggers a # post-processing event. events = [] def on_event(event): # noqa: E306 if isinstance(event, ConfigurationUpdatedEvent): # Record both the event and the top overlay. events.append(event.config.overlays[0].name) # Do two pushes, and then pop one of them. with event_subscribers(on_event): with configuration('test', _configname='first'): with configuration('test', _configname='second'): pass self.assertEqual(events, ['first', 'second', 'first']) def test_config_template_dir_is_source(self): # This test will leave a 'var' directory in the top-level source # directory. Be sure to clean it up. config = Configuration() with ExitStack() as resources: fp = resources.enter_context( NamedTemporaryFile('w', encoding='utf-8')) var_dir = resources.enter_context(TemporaryDirectory()) # Don't let the post-processing after the config.load() to put a # 'var' directory in the source tree's top level directory. print("""\ [paths.here] template_dir: :source: var_dir: {} """.format(var_dir), file=fp) fp.flush() config.load(fp.name) import mailman.templates self.assertEqual(config.TEMPLATE_DIR, os.path.dirname(mailman.templates.__file__)) class TestExternal(unittest.TestCase): """Test external configuration file loading APIs.""" def test_load_external_by_filename(self): filename = resource_filename('mailman.config', 'postfix.cfg') contents = load_external(filename) self.assertEqual(contents[:9], '[postfix]') def test_load_external_by_path(self): contents = load_external('python:mailman.config.postfix') self.assertEqual(contents[:9], '[postfix]') def test_external_configuration_by_filename(self): filename = resource_filename('mailman.config', 'postfix.cfg') parser = external_configuration(filename) self.assertEqual(parser.get('postfix', 'postmap_command'), '/usr/sbin/postmap') def test_external_configuration_by_path(self): parser = external_configuration('python:mailman.config.postfix') self.assertEqual(parser.get('postfix', 'postmap_command'), '/usr/sbin/postmap') def test_missing_configuration_file(self): with self.assertRaises(MissingConfigurationFileError) as cm: external_configuration('path:mailman.config.missing') self.assertEqual(cm.exception.path, 'path:mailman.config.missing') class TestConfigurationErrors(unittest.TestCase): layer = ConfigLayer def test_bad_path_layout_specifier(self): # Using a [mailman]layout name that doesn't exist is a fatal error. config = Configuration() with ExitStack() as resources: fp = resources.enter_context( NamedTemporaryFile('w', encoding='utf-8')) print("""\ [mailman] layout: nonesuch """, file=fp) fp.flush() # Suppress warning messages in the test output. Also, make sure # that the config.load() call doesn't break global state. resources.enter_context(mock.patch('sys.stderr')) resources.enter_context(mock.patch.object(config, '_clear')) cm = resources.enter_context(self.assertRaises(SystemExit)) config.load(fp.name) self.assertEqual(cm.exception.args, (1,)) def test_path_expansion_infloop(self): # A path expansion never completes because it references a non-existent # substitution variable. config = Configuration() with ExitStack() as resources: fp = resources.enter_context( NamedTemporaryFile('w', encoding='utf-8')) print("""\ [paths.here] log_dir: $nopath/log_dir """, file=fp) fp.flush() # Suppress warning messages in the test output. Also, make sure # that the config.load() call doesn't break global state. resources.enter_context(mock.patch('sys.stderr')) resources.enter_context(mock.patch.object(config, '_clear')) cm = resources.enter_context(self.assertRaises(SystemExit)) config.load(fp.name) self.assertEqual(cm.exception.args, (1,)) mailman-3.1.1/src/mailman/config/tests/__init__.py0000664000175000017500000000000012632220112023154 0ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/config/tests/test_archivers.py0000664000175000017500000000342613066532160024474 0ustar maxkingmaxking00000000000000# Copyright (C) 2013-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Site-wide archiver configuration tests.""" import unittest from mailman.config import config from mailman.testing.helpers import configuration from mailman.testing.layers import ConfigLayer class TestArchivers(unittest.TestCase): layer = ConfigLayer def test_enabled(self): # By default, the testing configuration enables some archivers. archivers = {} for archiver in config.archivers: archivers[archiver.name] = archiver self.assertFalse(archivers['prototype'].is_enabled) self.assertTrue(archivers['mail-archive'].is_enabled) self.assertTrue(archivers['mhonarc'].is_enabled) @configuration('archiver.mhonarc', enable='no') def test_disabled(self): # We just disabled one of the archivers. archivers = {} for archiver in config.archivers: archivers[archiver.name] = archiver self.assertFalse(archivers['prototype'].is_enabled) self.assertTrue(archivers['mail-archive'].is_enabled) self.assertFalse(archivers['mhonarc'].is_enabled) mailman-3.1.1/src/mailman/config/__init__.py0000664000175000017500000000156113066532160022042 0ustar maxkingmaxking00000000000000# Copyright (C) 2008-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Mailman configuration package.""" from mailman.config.config import Configuration from public import public public(config=Configuration()) mailman-3.1.1/src/mailman/config/passlib.cfg0000664000175000017500000000054113066532160022044 0ustar maxkingmaxking00000000000000[passlib] # This is the output of passlibs.apps.custom_app_context.to_string(). # See http://packages.python.org/passlib/index.html for details. schemes = sha512_crypt, sha256_crypt default = sha512_crypt sha256_crypt__min_rounds = 80000 sha512_crypt__min_rounds = 60000 admin__sha256_crypt__min_rounds = 160000 admin__sha512_crypt__min_rounds = 120000 mailman-3.1.1/src/mailman/config/alembic.cfg0000664000175000017500000000147113066532160022006 0ustar maxkingmaxking00000000000000# Copyright (C) 2014-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . [alembic] # Path to Alembic migration scripts. script_location: mailman.database:alembic mailman-3.1.1/src/mailman/config/schema.cfg0000664000175000017500000007202513203705633021655 0ustar maxkingmaxking00000000000000# Copyright (C) 2008-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . # This is the GNU Mailman configuration schema. It defines the default # configuration options for the core system and plugins. It uses ini-style # formats under the lazr.config regime to define all system configuration # options. See for details. [mailman] # This address is the "site owner" address. Certain messages which must be # delivered to a human, but which can't be delivered to a list owner (e.g. a # bounce from a list owner), will be sent to this address. It should point to # a human. site_owner: changeme@example.com # This is the local-part of an email address used in the From field whenever a # message comes from some entity to which there is no natural reply recipient. # Mailman will append '@' and the host name of the list involved. This # address must not bounce and it must not point to a Mailman process. noreply_address: noreply # The default language for this server. default_language: en # Membership tests for posting purposes are usually performed by looking at a # set of headers, passing the test if any of their values match a member of # the list. Headers are checked in the order given in this variable. The # value From_ means to use the envelope sender. Field names are case # insensitive. This is a space separate list of headers. sender_headers: from from_ reply-to sender # Mail command processor will ignore mail command lines after designated max. email_commands_max_lines: 10 # Default length of time a pending request is live before it is evicted from # the pending database. pending_request_life: 3d # How long should files be saved before they are evicted from the cache? cache_life: 7d # A callable to run with no arguments early in the initialization process. # This runs before database initialization. pre_hook: # A callable to run with no arguments late in the initialization process. # This runs after adapters are initialized. post_hook: # Which paths.* file system layout to use. layout: here # Can MIME filtered messages be preserved by list owners? filtered_messages_are_preservable: no # How should text/html parts be converted to text/plain when the mailing list # is set to convert HTML to plaintext? This names a command to be called, # where the substitution variable $filename is filled in by Mailman, and # contains the path to the temporary file that the command should read from. # The command should print the converted text to stdout. html_to_plain_text_command: /usr/bin/lynx -dump $filename # Specify what characters are allowed in list names. Characters outside of # the class [-_.+=!$*{}~0-9a-z] matched case insensitively are never allowed, # but this specifies a subset as the only allowable characters. This must be # a valid character class regexp or the effect on list creation is # unpredictable. listname_chars: [-_.0-9a-z] [shell] # `mailman shell` (also `withlist`) gives you an interactive prompt that you # can use to interact with an initialized and configured Mailman system. Use # --help for more information. This section allows you to configure certain # aspects of this interactive shell. # Customize the interpreter prompt. prompt: >>> # Banner to show on startup. banner: Welcome to the GNU Mailman shell # Use IPython as the shell, which must be found on the system. Valid values # are `no`, `yes`, and `debug` where the latter is equivalent to `yes` except # that any import errors will be displayed to stderr. use_ipython: no # Set this to allow for command line history if readline is available. This # can be as simple as $var_dir/history.py to put the file in the var directory. history_file: [paths.master] # Important directories for Mailman operation. These are defined here so that # different layouts can be supported. For example, a developer layout would # be different from a FHS layout. Most paths are based off the var_dir, and # often just setting that will do the right thing for all the other paths. # You might also have to set spool_dir though. # # Substitutions are allowed, but must be of the form $var where 'var' names a # configuration variable in the paths.* section. Substitutions are expanded # recursively until no more $-variables are present. Beware of infinite # expansion loops! # # This is the root of the directory structure that Mailman will use to store # its run-time data. var_dir: /var/tmp/mailman # This is where the Mailman queue files directories will be created. queue_dir: $var_dir/queue # This is the directory containing the Mailman 'runner' and 'master' commands # if set to the string '$argv', it will be taken as the directory containing # the 'mailman' command. bin_dir: $argv # All list-specific data. list_data_dir: $var_dir/lists # Directory where log files go. log_dir: $var_dir/logs # Directory for system-wide locks. lock_dir: $var_dir/locks # Directory for system-wide data. data_dir: $var_dir/data # Cache files. cache_dir: $var_dir/cache # Directory for configuration files and such. etc_dir: $var_dir/etc # Directory containing Mailman plugins. ext_dir: $var_dir/ext # Directory where the default IMessageStore puts its messages. messages_dir: $var_dir/messages # Directory for archive backends to store their messages in. Archivers should # create a subdirectory in here to store their files. archive_dir: $var_dir/archives # Root directory for site-specific template override files. template_dir: $var_dir/templates # There are also a number of paths to specific file locations that can be # defined. For these, the directory containing the file must already exist, # or be one of the directories created by Mailman as per above. # # This is where PID file for the master runner is stored. pid_file: $var_dir/master.pid # Lock file. lock_file: $lock_dir/master.lck [devmode] # Setting enabled to true enables certain safeguards and other behavior # changes that make developing Mailman easier. For example, it forces the # SMTP RCPT TO recipients to be a test address so that no messages are # accidentally sent to real addresses. enabled: no # Set this to an address to force the SMTP RCPT TO recipents when devmode is # enabled. This way messages can't be accidentally sent to real addresses. recipient: # This gets set by the testing layers so that the runner subprocesses produce # predictable dates and times. testing: no # Time-outs for starting up various test subprocesses, such as the LMTP and # REST servers. This is only used for the test suite, so if you're seeing # test failures, try increasing the wait time. wait: 60s [passwords] # Where can we find the passlib configuration file? The path can be either a # file system path or a Python import path. If the value starts with python: # then it is a Python import path, otherwise it is a file system path. File # system paths must be absolute since no guarantees are made about the current # working directory. Python paths should not include the trailing .cfg, which # the file must end with. configuration: python:mailman.config.passlib # When Mailman generates them, this is the default length of passwords. password_length: 8 [runner.master] # Define which runners, and how many of them, to start. # The full import path to the class for this runner. class: mailman.core.runner.Runner # The queue directory path that this runner scans. This is ignored for # runners that don't manage a queue directory. path: $QUEUE_DIR/$name # The number of parallel runners. This must be a power of 2. This is ignored # for runners that don't manage a queue directory. instances: 1 # Whether to start this runner or not. start: yes # The maximum number of restarts for this runner. When the runner exits # because of an error or other unexpected problem, it is automatically # restarted, until the maximum number of restarts has been reached. max_restarts: 10 # The sleep interval for the runner. It wakes up once every interval to # process the files in its slice of the queue directory. Some runners may # ignore this. sleep_time: 1s [database] # The class implementing the IDatabase. class: mailman.database.sqlite.SQLiteDatabase # Use this to set the Storm database engine URL. You generally have one # primary database connection for all of Mailman. List data and most rosters # will store their data in this database, although external rosters may access # other databases in their own way. This string supports standard # 'configuration' substitutions. url: sqlite:///$DATA_DIR/mailman.db debug: no [logging.template] # This defines various log settings. The options available are: # # - level -- Overrides the default level; this may be any of the # standard Python logging levels, case insensitive. # - format -- Overrides the default format string # - datefmt -- Overrides the default date format string # - path -- Overrides the default logger path. This may be a relative # path name, in which case it is relative to Mailman's LOG_DIR, # or it may be an absolute path name. You cannot change the # handler class that will be used. # - propagate -- Boolean specifying whether to propagate log message from this # logger to the root "mailman" logger. You cannot override # settings for the root logger. # # In this section, you can define defaults for all loggers, which will be # prefixed by 'mailman.'. Use subsections to override settings for specific # loggers. The names of the available loggers are: # # - archiver -- All archiver output # - bounce -- All bounce processing logs go here # - config -- Configuration issues # - database -- Database logging (SQLAlchemy and Alembic) # - debug -- Only used for development # - error -- All exceptions go to this log # - fromusenet -- Information related to the Usenet to Mailman gateway # - http -- Internal wsgi-based web interface # - locks -- Lock state changes # - mischief -- Various types of hostile activity # - runner -- Runner process start/stops # - smtp -- Successful SMTP activity # - smtp-failure -- Unsuccessful SMTP activity # - subscribe -- Information about leaves/joins # - vette -- Message vetting information format: %(asctime)s (%(process)d) %(message)s datefmt: %b %d %H:%M:%S %Y propagate: no level: info path: mailman.log [logging.root] [logging.archiver] [logging.bounce] path: bounce.log [logging.config] [logging.database] level: warn [logging.debug] path: debug.log level: info [logging.error] [logging.fromusenet] [logging.http] [logging.locks] [logging.mischief] [logging.runner] [logging.smtp] path: smtp.log # The smtp logger defines additional options for handling the logging of each # attempted delivery. These format strings specify what information is logged # for every message, every successful delivery, every refused delivery and # every recipient failure. To disable a status message, set the value to 'no' # (without the quotes). # # These template strings accept the following set of substitution # placeholders, if available. # # msgid -- the Message-ID of the message in question # listname -- the fully-qualified list name # sender -- the sender if available # recip -- the recipient address if available, or the number of # recipients being delivered to # size -- the approximate size of the message in bytes # seconds -- the number of seconds the operation took # refused -- the number of refused recipients # smtpcode -- the SMTP success or failure code # smtpmsg -- the SMTP success or failure message every: $msgid smtp to $listname for $recip recips, completed in $time seconds success: $msgid post to $listname from $sender, $size bytes refused: $msgid post to $listname from $sender, $size bytes, $refused failures failure: $msgid delivery to $recip failed with code $smtpcode, $smtpmsg [logging.subscribe] [logging.vette] [webservice] # The hostname at which admin web service resources are exposed. hostname: localhost # The port at which the admin web service resources are exposed. port: 8001 # Whether or not requests to the web service are secured through SSL. use_https: no # Whether or not to show tracebacks in an HTTP response for a request that # raised an exception. show_tracebacks: yes # The API version number for the current (highest) API. api_version: 3.1 # The administrative username. admin_user: restadmin # The administrative password. admin_pass: restpass [language.master] # Template for language definitions. The section name must be [language.xx] # where xx is the 2-character ISO code for the language. # The English name for the language. description: English (USA) # And the default character set for the language. charset: us-ascii # Whether the language is enabled or not. enabled: yes # Language charsets as imported from Mailman 2.1 defaults # Ref: http://www.lingoes.net/en/translator/langcode.htm [language.ar] description: Arabic charset: utf-8 enabled: yes [language.ast] description: Asturian charset: iso-8859-1 enabled: yes [language.ca] description: Catalan charset: utf-8 enabled: yes [language.cs] description: Czech charset: iso-8859-2 enabled: yes [language.da] description: Danish charset: iso-8859-1 enabled: yes [language.de] description: German charset: iso-8859-1 enabled: yes [language.el] description: Greek charset: iso-8859-7 enabled: yes [language.es] description: Spanish charset: iso-8859-1 enabled: yes [language.et] description: Estonian charset: iso-8859-15 enabled: yes [language.eu] # Basque description: Euskara charset: iso-8859-15 enabled: yes [language.fi] description: Finnish charset: iso-8859-1 enabled: yes [language.fr] description: French charset: iso-8859-1 enabled: yes [language.gl] description: Galician charset: utf-8 enabled: yes [language.he] description: Hebrew charset: utf-8 enabled: yes [language.hr] description: Croatian charset: iso-8859-2 enabled: yes [language.hu] description: Hungarian charset: iso-8859-2 enabled: yes [language.ia] description: Interlingua charset: iso-8859-15 enabled: yes [language.it] description: Italian charset: iso-8859-1 enabled: yes [language.ja] description: Japanese charset: euc-jp enabled: yes [language.ko] description: Korean charset: euc-kr enabled: yes [language.lt] description: Lithuanian charset: iso-8859-13 enabled: yes [language.nl] description: Dutch charset: iso-8859-1 enabled: yes [language.no] description: Norwegian charset: iso-8859-1 enabled: yes [language.pl] description: Polish charset: iso-8859-2 enabled: yes [language.pt] description: Protuguese charset: iso-8859-1 enabled: yes [language.pt_BR] description: Protuguese (Brazil) charset: iso-8859-1 enabled: yes [language.ro] description: Romanian charset: iso-8859-2 enabled: yes [language.ru] description: Russian charset: koi8-r enabled: yes [language.sk] description: Slovak charset: utf-8 enabled: yes [language.sl] description: Slovenian charset: iso-8859-2 enabled: yes [language.sr] description: Serbian charset: utf-8 enabled: yes [language.sv] description: Swedish charset: iso-8859-1 enabled: yes [language.tr] description: Turkish charset: iso-8859-9 enabled: yes [language.uk] description: Ukrainian charset: utf-8 enabled: yes [language.vi] description: Vietnamese charset: utf-8 enabled: yes [language.zh_CN] description: Chinese charset: utf-8 enabled: yes [language.zh_TW] description: Chinese (Taiwan) charset: utf-8 enabled: yes [antispam] # This section defines basic antispam detection settings. # This value contains lines which specify RFC 822 headers in the email to # check for spamminess. Each line contains a `key: value` pair, where the key # is the header to check and the value is a Python regular expression to match # against the header's value. Multiple checks should be entered as multiline # value with leading spaces: # # header_checks: # X-Spam: (yes|maybe) # Authentication-Results: mail.example.com; dmarc=(fail|quarantine) # # The header value and regular expression are always matched # case-insensitively. header_checks: # The chain to jump to if any of the header patterns matches. This must be # the name of an existing chain such as 'discard', 'reject', 'hold', or # 'accept', otherwise 'hold' will be used. jump_chain: hold [mta] # The class defining the interface to the incoming mail transport agent. incoming: mailman.mta.postfix.LMTP # The callable implementing delivery to the outgoing mail transport agent. # This must accept three arguments, the mailing list, the message, and the # message metadata dictionary. outgoing: mailman.mta.deliver.deliver # How to connect to the outgoing MTA. If smtp_user and smtp_pass is given, # then Mailman will attempt to log into the MTA when making a new connection. smtp_host: localhost smtp_port: 25 smtp_user: smtp_pass: # Where the LMTP server listens for connections. Use 127.0.0.1 instead of # localhost for Postfix integration, because Postfix only consults DNS # (e.g. not /etc/hosts). lmtp_host: 127.0.0.1 lmtp_port: 8024 # Ceiling on the number of recipients that can be specified in a single SMTP # transaction. Set to 0 to submit the entire recipient list in one # transaction. max_recipients: 500 # Ceiling on the number of SMTP sessions to perform on a single socket # connection. Some MTAs have limits. Set this to 0 to do as many as we like # (i.e. your MTA has no limits). Set this to some number great than 0 and # Mailman will close the SMTP connection and re-open it after this number of # consecutive sessions. max_sessions_per_connection: 0 # Maximum number of simultaneous subthreads that will be used for SMTP # delivery. After the recipients list is chunked according to max_recipients, # each chunk is handed off to the SMTP server by a separate such thread. If # your Python interpreter was not built for threads, this feature is disabled. # You can explicitly disable it in all cases by setting max_delivery_threads # to 0. max_delivery_threads: 0 # How long should messages which have delivery failures continue to be # retried? After this period of time, a message that has failed recipients # will be dequeued and those recipients will never receive the message. delivery_retry_period: 5d # These variables control the format and frequency of VERP-like delivery for # better bounce detection. VERP is Variable Envelope Return Path, defined # here: # # http://cr.yp.to/proto/verp.txt # # This involves encoding the address of the recipient as Mailman knows it into # the envelope sender address (i.e. RFC 5321 MAIL FROM). Thus, no matter what # kind of forwarding the recipient has in place, should it eventually bounce, # we will receive an unambiguous notice of the bouncing address. # # However, we're technically only "VERP-like" because we're doing the envelope # sender encoding in Mailman, not in the MTA. We do require cooperation from # the MTA, so you must be sure your MTA can be configured for extended address # semantics. # # The first variable describes how to encode VERP envelopes. It must contain # these three string interpolations, which get filled in by Mailman: # # $bounces -- the list's -bounces robot address will be set here # $local -- the recipient address's local mailbox part will be set here # $domain -- the recipient address's domain name will be set here # # This example uses the default below. # # FQDN list address is: mylist@dom.ain # Recipient is: aperson@a.nother.dom # # The envelope sender will be mylist-bounces+aperson=a.nother.dom@dom.ain # # Note that your MTA /must/ be configured to deliver such an addressed message # to mylist-bounces! verp_delimiter: + verp_format: ${bounces}+${local}=${domain} # For nicer confirmation emails, use a VERP-like format which encodes the # confirmation cookie in the reply address. This lets us put a more user # friendly Subject: on the message, but requires cooperation from the MTA. # Format is like verp_format, but with the following substitutions: # # $address -- the list-confirm address # $cookie -- the confirmation cookie verp_confirm_format: $address+$cookie # This regular expression unambiguously decodes VERP addresses, which will be # placed in the To: (or other, depending on the MTA) header of the bounce # message by the bouncing MTA. Getting this right is critical -- and tricky. # Learn your Python regular expressions. It must define exactly three named # groups, `bounces`, `local` and `domain`, with the same definition as above. # It will be compiled case-insensitively. verp_regexp: ^(?P[^+]+?)\+(?P[^=]+)=(?P[^@]+)@.*$ # This is analogous to verp_regexp, but for splitting apart the # verp_confirm_format. MUAs have been observed that mung # # From: local_part@host # # into # # To: "local_part" # # when replying, so we skip everything up to '<' if any. verp_confirm_regexp: ^(.*<)?(?P[^+]+?)\+(?P[^@]+)@.*$ # Set this to 'yes' to enable VERP-like (more user friendly) confirmations. verp_confirmations: no # Another good opportunity is when regular delivery is personalized. Here # again, we're already incurring the performance hit for addressing each # individual recipient. Set this to 'yes' to enable VERPs on all personalized # regular deliveries (personalized digests aren't supported yet). verp_personalized_deliveries: no # And finally, we can VERP normal, non-personalized deliveries. However, # because it can be a significant performance hit, we allow you to decide how # often to VERP regular deliveries. This is the interval, in number of # messages, to do a VERP recipient address. The same variable controls both # regular and digest deliveries. Set to 0 to disable occasional VERPs, set to # 1 to VERP every delivery, or to some number > 1 for only occasional VERPs. verp_delivery_interval: 0 # VERP format and regexp for probe messages. verp_probe_format: $bounces+$token@$domain verp_probe_regexp: ^(?P[^+]+?)\+(?P[^@]+)@.*$ # Set this 'yes' to activate VERP probe for disabling by bounce. verp_probes: no # This is the maximum number of automatic responses sent to an address because # of -request messages or posting hold messages. This limit prevents response # loops between Mailman and misconfigured remote email robots. Mailman # already inhibits automatic replies to any message labeled with a header # "Precendence: bulk|list|junk". This is a fallback safety valve so it should # be set fairly high. Set to 0 for no limit (probably useful only for # debugging). max_autoresponses_per_day: 10 # Some list posts and mail to the -owner address may contain DomainKey or # DomainKeys Identified Mail (DKIM) signature headers . # Various list transformations to the message such as adding a list header or # footer or scrubbing attachments or even reply-to munging can break these # signatures. It is generally felt that these signatures have value, even if # broken and even if the outgoing message is resigned. However, some sites # may wish to remove these headers by setting this to 'yes'. remove_dkim_headers: no # Where can we find the mail server specific configuration file? The path can # be either a file system path or a Python import path. If the value starts # with python: then it is a Python import path, otherwise it is a file system # path. File system paths must be absolute since no guarantees are made about # the current working directory. Python paths should not include the trailing # .cfg, which the file must end with. configuration: python:mailman.config.postfix [bounces] # How often should the bounce runner process queued detected bounces? register_bounces_every: 15m [archiver.master] # To add new archivers, define a new section based on this one, overriding the # following values. # The class implementing the IArchiver interface. class: # Set this to 'yes' to enable the archiver. enable: no # Additional configuration for the archiver. The path can be either a file # system path or a Python import path. If the value starts with python: then # it is a Python import path, otherwise it is a file system path. File system # paths must be absolute since no guarantees are made about the current # working directory. Python paths should not include the trailing .cfg, which # the file must end with. configuration: changeme # When sending the message to the archiver, you have the option of # "clobbering" the Date: header, specifically to make it more sane. Some # archivers can't handle dates that are wildly off from reality. This does # not change the Date: header for any other delivery vector except this # specific archive. # # When the original Date header is clobbered, it will always be stored in # X-Original-Date. The new Date header will always be set to the date at # which the messages was received by the Mailman server, in UTC. # # Your options here are: # * never -- Leaves the original Date header alone. # * always -- Always override the Date header. # * maybe -- Override the Date only if it is outside the clobber_skew period. clobber_date: maybe clobber_skew: 1d [archiver.mhonarc] # This is the stock MHonArc archiver. class: mailman.archiving.mhonarc.MHonArc configuration: python:mailman.config.mhonarc [archiver.mail_archive] # This is the stock mail-archive.com archiver. class: mailman.archiving.mailarchive.MailArchive configuration: python:mailman.config.mail_archive [archiver.prototype] # This is a prototypical sample archiver. class: mailman.archiving.prototype.Prototype [styles] # Python import paths inside which components are searched for which implement # the IStyle interface. Use one path per line. paths: mailman.styles # The default style to apply if nothing else was requested. The value is the # name of an existing style. If no such style exists, no style will be # applied. default: legacy-default [digests] # Headers which should be kept in both RFC 1153 (plain) and MIME digests. RFC # 1153 also specifies these headers in this exact order, so order matters. # These are space separated and case insensitive. mime_digest_keep_headers: Date From To Cc Subject Message-ID Keywords In-Reply-To References Content-Type MIME-Version Content-Transfer-Encoding Precedence Reply-To Message List-Post plain_digest_keep_headers: Message Date From Subject To Cc Message-ID Keywords Content-Type [nntp] # Set these variables if you need to authenticate to your NNTP server for # Usenet posting or reading. Leave these blank if no authentication is # necessary. user: password: # Host and port of the NNTP server to connect to. Leave these blank to use # the default localhost:119. host: port: # This controls how headers must be cleansed in order to be accepted by your # NNTP server. Some servers like INN reject messages containing prohibited # headers, or duplicate headers. The NNTP server may reject the message for # other reasons, but there's little that can be programmatically done about # that. # # These headers (case ignored) are removed from the original message. This is # a whitespace separate list of headers. remove_headers: nntp-posting-host nntp-posting-date x-trace x-complaints-to xref date-received posted posting-version relay-version received # These headers are left alone, unless there are duplicates in the original # message. Any second and subsequent headers are rewritten to the second # named header (case preserved). This is a list of header pairs, one pair per # line. rewrite_duplicate_headers: To X-Original-To CC X-Original-CC Content-Transfer-Encoding X-Original-Content-Transfer-Encoding MIME-Version X-MIME-Version [dmarc] # RFC 7489 - Domain-based Message Authentication, Reporting, and Conformance. # https://en.wikipedia.org/wiki/DMARC # Parameters for DMARC DNS lookups. If you are seeing 'DNSException: Unable # to query DMARC policy ...' entries in your error log, you may need to adjust # these. # # The time to wait for a response from a name server before timeout. resolver_timeout: 3s # The total time to spend trying to get an answer to the DNS question. resolver_lifetime: 5s # A URL from which to retrieve the data for the algorithm that computes # Organizational Domains for DMARC policy lookup purposes. This can be # anything handled by the Python urllib.request.urlopen function. See # https://publicsuffix.org/list/ for info. org_domain_data_url: https://publicsuffix.org/list/public_suffix_list.dat # How long should the local suffix list be used before it's considered out of # date. After this amount of time a new list will be downloaded, but if it # can't be accessed, old data will still be used. cache_lifetime: 7d mailman-3.1.1/src/mailman/config/docs/0000775000175000017500000000000013204154701020651 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/config/docs/config.rst0000664000175000017500000001362513203223435022657 0ustar maxkingmaxking00000000000000.. _configuration: ===================== Configuring Mailman ===================== Mailman is configured via an "ini"-style configuration file, usually called ``mailman.cfg``. Most of the defaults produce a usable system, but you will almost certainly have to set up a few things before you run Mailman for the first time. You only need to include those settings which you want to change; everything else is inherited. These file system paths are searched in the following order to find your site's custom ``mailman.cfg`` file. The first file found is used. * The file system path specified by the environment variable ``$MAILMAN_CONFIG_FILE`` * ``mailman.cfg`` in the current working directory * ``var/etc/mailman.cfg`` relative to the current working directory * ``$HOME/.mailman.cfg`` * ``/etc/mailman.cfg`` * ``/etc/mailman3/mailman.cfg`` * ``../../etc/mailman.cfg`` relative to the working directory of ``argv[0]`` You can also use the ``-C`` option to specify an explicit path, and this always takes precedence. See ``mailman --help`` for more details. You **must** restart Mailman for any changes to take effect. Which configuration file is in use? =================================== Mailman itself will tell you which configuration file is being used when you run the ``mailman info`` command:: $ mailman info GNU Mailman 3.1.0b4 (Between The Wheels) Python 3.5.3 (default, Jan 19 2017, 14:11:04) [GCC 6.3.0 20170118] config file: /home/mailman/var/etc/mailman.cfg db url: sqlite:////home/mailman/var/data/mailman.db devmode: DISABLED REST root url: http://localhost:8001/3.1/ REST credentials: restadmin:restpass The first time you run this command it will create the configuration file and directory using the built-in defaults, so use ``-C`` to specify an alternative location. Of course the ``info`` subcommand shows you other interesting things about your Mailman instance. Schemas, templates, and master sections ======================================= Mailman's configuration system is built on top of `lazr.config `_ although in general the details aren't important. Basically there is a ``schema.cfg`` file included in the source tree, which defines all the available sections and variables, along with global defaults. There is a built-in base ``mailman.cfg`` file also included in the source tree, which further refines the defaults. Your custom ``mailman.cfg`` file, found using the search locations described above, provides the final override for these settings. The ``schema.cfg`` file describes every section, variable, and permissible values, so you should consult this for more details. The ``schema.cfg`` file is included verbatim below. You will notice two types of special sections in the ``schema.cfg`` files; those that end with the ``.template`` suffix, and others which end in a ``.master`` suffix. There are no other special sections. Templates provide exactly that: a template for other similarly named sections. So for example, you will see a section labeled ``logging.template`` which provides some configuration variables and some basic defaults. You will also see a section called ``logging.bounce`` which refines the ``logging.template`` section by overriding one or more settings. If you wanted to change the default logging level for the database component in Mailman, say from ``warn`` to ``info``, you would add this to your ``mailman.cfg`` file:: [logging.database] level: info Generally you won't add new template specialization sections; everything you need is already defined. You will also see sections labeled with the ``.master`` suffix. For the most part you can treat these exactly the same as ``.template`` sections; the differences are only relevant for Mailman developers [#]_. An example of a ``.master`` section is ``[runner.master]`` which is used to define the defaults for all the :ref:`runner processes `. This is specialized in the built-in ``mailman.cfg`` file, where you'll see sections like ``[runner.archive]`` and ``[runner.in]``. You won't need to specially the master section yourself, but instead you can override some settings in the individual runner sections. How do I change a setting? ========================== If you think you want to change something, it can be a little tricky to find exactly the setting you'll need. The first step is to use the ``mailman conf`` command to print all the current variables and their values. With no options, this will print all the hundreds of (sorted!) available settings to standard output. You can narrow this down in two ways. You can print just the values of a particular section:: $ mailman conf -s webservice [webservice] admin_pass: restpass [webservice] admin_user: restadmin [webservice] api_version: 3.1 [webservice] hostname: localhost [webservice] port: 8001 [webservice] show_tracebacks: yes [webservice] use_https: no Let's say you wanted to change the port the REST API listens on. Just add this to your ``mailman.cfg`` file:: [webservice] port: 8080 You can also search for a specific setting:: $ mailman conf -k prompt [shell] prompt: >>> The ``mailman conf`` command does not provide documentation about sections or variables. In order to get more information about what a particular variable controls, read the ``schema.cfg`` and built-in base ``mailman.cfg`` file. schema.cfg ========== ``schema.cfg`` defines the ini-file schema and contains documentation for every section and configuration variable. .. literalinclude:: ../schema.cfg mailman.cfg =========== Configuration settings provided in the built-in base ``mailman.cfg`` file overrides those provided in ``schema.cfg``. .. literalinclude:: ../mailman.cfg .. [#] The technical differences are described in the `lazr.config `_ package, upon which Mailman's configuration system is based. mailman-3.1.1/src/mailman/config/mhonarc.cfg0000664000175000017500000000215313066532160022037 0ustar maxkingmaxking00000000000000# Copyright (C) 2008-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . # This is the configuration file for the MHonArc archiver [general] # The base url for the archiver. This is used to to calculate links to # individual messages in the archive. base_url: http://$hostname/archives/$fqdn_listname # If the archiver works by calling a command on the local machine, this is the # command to call. command: /usr/bin/mhonarc -outdir /path/to/archive/$listname -add mailman-3.1.1/src/mailman/config/config.py0000664000175000017500000002716113203705633021554 0ustar maxkingmaxking00000000000000# Copyright (C) 2006-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Configuration file loading and management.""" import os import sys import mailman.templates from configparser import ConfigParser from flufl.lock import Lock from lazr.config import ConfigSchema, as_boolean from mailman import version from mailman.interfaces.configuration import ( ConfigurationUpdatedEvent, IConfiguration, MissingConfigurationFileError) from mailman.interfaces.languages import ILanguageManager from mailman.utilities.filesystem import makedirs from mailman.utilities.modules import call_name, expand_path from pkg_resources import resource_filename, resource_string as resource_bytes from public import public from string import Template from zope.component import getUtility from zope.event import notify from zope.interface import implementer SPACE = ' ' SPACERS = '\n' MAILMAN_CFG_TEMPLATE = """\ # AUTOMATICALLY GENERATED BY MAILMAN ON {} UTC # # This is your GNU Mailman 3 configuration file. You can edit this file to # configure Mailman to your needs, and Mailman will never overwrite it. # Additional configuration information is available here: # # http://mailman.readthedocs.io/en/latest/src/mailman/config/docs/config.html # # For example, uncomment the following lines to run Mailman in developer mode. # # [devmode] # enabled: yes # recipient: your.address@your.domain""" @public @implementer(IConfiguration) class Configuration: """The core global configuration object.""" def __init__(self): self.switchboards = {} self.QFILE_SCHEMA_VERSION = version.QFILE_SCHEMA_VERSION self._config = None self.filename = None # Whether to create run-time paths or not. This is for the test # suite, which will set this to False until the test layer is set up. self.create_paths = True # Create various registries. self.chains = {} self.rules = {} self.handlers = {} self.pipelines = {} self.commands = {} self.password_context = None def _clear(self): """Clear the cached configuration variables.""" self.switchboards.clear() getUtility(ILanguageManager).clear() def __getattr__(self, name): """Delegate to the configuration object.""" return getattr(self._config, name) def __iter__(self): return iter(self._config) def load(self, filename=None): """Load the configuration from the schema and config files.""" schema_file = resource_filename('mailman.config', 'schema.cfg') schema = ConfigSchema(schema_file) # If a configuration file was given, load it now too. First, load # the absolute minimum default configuration, then if a # configuration filename was given by the user, push it. config_file = resource_filename('mailman.config', 'mailman.cfg') self._config = schema.load(config_file) if filename is None: self._post_process() else: self.filename = filename with open(filename, 'r', encoding='utf-8') as user_config: self.push(filename, user_config.read()) def push(self, config_name, config_string): """Push a new configuration onto the stack.""" self._clear() self._config.push(config_name, config_string) self._post_process() def pop(self, config_name): """Pop a configuration from the stack.""" self._clear() self._config.pop(config_name) self._post_process() def _post_process(self): """Perform post-processing after loading the configuration files.""" # Expand and set up all directories. self._expand_paths() self.ensure_directories_exist() notify(ConfigurationUpdatedEvent(self)) def _expand_paths(self): """Expand all configuration paths.""" # Set up directories. default_bin_dir = os.path.abspath(os.path.dirname(sys.executable)) # Now that we've loaded all the configuration files we're going to # load, set up some useful directories based on the settings in the # configuration file. layout = 'paths.' + self._config.mailman.layout for category in self._config.getByCategory('paths'): if category.name == layout: break else: print('No path configuration found:', layout, file=sys.stderr) sys.exit(1) # First, collect all variables in a substitution dictionary. $VAR_DIR # is taken from the environment or from the configuration file if the # environment is not set. Because the var_dir setting in the config # file could be a relative path, and because 'mailman start' chdirs to # $VAR_DIR, without this subprocesses bin/master and bin/runner will # create $VAR_DIR hierarchies under $VAR_DIR when that path is # relative. var_dir = os.environ.get('MAILMAN_VAR_DIR', category.var_dir) substitutions = dict( cwd=os.getcwd(), argv=default_bin_dir, var_dir=var_dir, template_dir=( os.path.dirname(mailman.templates.__file__) if category.template_dir == ':source:' else category.template_dir), ) # Directories. for name in ('archive', 'bin', 'cache', 'data', 'etc', 'ext', 'list_data', 'lock', 'log', 'messages', 'queue'): key = '{}_dir'.format(name) substitutions[key] = getattr(category, key) # Files. for name in ('lock', 'pid'): key = '{}_file'.format(name) substitutions[key] = getattr(category, key) # Add the path to the .cfg file, if one was given on the command line. if self.filename is not None: substitutions['cfg_file'] = self.filename # Now, perform substitutions recursively until there are no more # variables with $-vars in them, or until substitutions are not # helping any more. last_dollar_count = 0 while True: expandables = [] # Mutate the dictionary during iteration. for key in substitutions: raw_value = substitutions[key] value = Template(raw_value).safe_substitute(substitutions) if '$' in value: # Still more work to do. expandables.append((key, value)) substitutions[key] = value if len(expandables) == 0: break if len(expandables) == last_dollar_count: print('Path expansion infloop detected:\n', SPACERS.join('\t{}: {}'.format(key, value) for key, value in sorted(expandables)), file=sys.stderr) sys.exit(1) last_dollar_count = len(expandables) # Ensure that all paths are normalized and made absolute. Handle the # few special cases first. Most of these are due to backward # compatibility. self.PID_FILE = os.path.abspath(substitutions.pop('pid_file')) for key in substitutions: attribute = key.upper() setattr(self, attribute, os.path.abspath(substitutions[key])) @property def logger_configs(self): """Return all log config sections.""" return self._config.getByCategory('logging', []) @property def paths(self): """Return a substitution dictionary of all path variables.""" return dict((k, self.__dict__[k]) for k in self.__dict__ if k.endswith('_DIR')) def ensure_directories_exist(self): """Create all path directories if they do not exist.""" if self.create_paths: for variable, directory in self.paths.items(): makedirs(directory) # Avoid circular imports. from mailman.utilities.datetime import now # Create a mailman.cfg template file if it doesn't already exist. # LBYL: , but it's probably okay because the directories # likely didn't exist before the above loop, and we'll create a # temporary lock. lock_file = os.path.join(self.LOCK_DIR, 'mailman-cfg.lck') mailman_cfg = os.path.join(self.ETC_DIR, 'mailman.cfg') with Lock(lock_file): if not os.path.exists(mailman_cfg): with open(mailman_cfg, 'w') as fp: print(MAILMAN_CFG_TEMPLATE.format( now().replace(microsecond=0)), file=fp) @property def runner_configs(self): """Iterate over all the runner configuration sections.""" yield from self._config.getByCategory('runner', []) @property def archivers(self): """Iterate over all the archivers.""" for section in self._config.getByCategory('archiver', []): class_path = section['class'].strip() if len(class_path) == 0: continue archiver = call_name(class_path) archiver.is_enabled = as_boolean(section.enable) yield archiver @property def language_configs(self): """Iterate over all the language configuration sections.""" yield from self._config.getByCategory('language', []) @public def load_external(path): """Load the configuration file named by path. :param path: A string naming the location of the external configuration file. This is either an absolute file system path or a special ``python:`` path. When path begins with ``python:``, the rest of the value must name a ``.cfg`` file located within Python's import path, however the trailing ``.cfg`` suffix is implied (don't provide it here). :return: The contents of the configuration file. :rtype: str """ # Is the context coming from a file system or Python path? if path.startswith('python:'): resource_path = path[7:] package, dot, resource = resource_path.rpartition('.') return resource_bytes(package, resource + '.cfg').decode('utf-8') with open(path, 'r', encoding='utf-8') as fp: return fp.read() @public def external_configuration(path): """Parse the configuration file named by path. :param path: A string naming the location of the external configuration file. This is either an absolute file system path or a special ``python:`` path. When path begins with ``python:``, the rest of the value must name a ``.cfg`` file located within Python's import path, however the trailing ``.cfg`` suffix is implied (don't provide it here). :return: A `ConfigParser` instance. """ # Is the context coming from a file system or Python path? cfg_path = expand_path(path) parser = ConfigParser() files = parser.read(cfg_path) if files != [cfg_path]: raise MissingConfigurationFileError(path) return parser mailman-3.1.1/src/mailman/config/mail_archive.cfg0000664000175000017500000000220313066532160023027 0ustar maxkingmaxking00000000000000# Copyright (C) 2008-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . # This is the configuration file for the mail-archive.com archiver [general] # The base url for the archiver. This is used to to calculate links to # individual messages in the archive. base_url: http://www.mail-archive.com/ # If the archiver works by getting a copy of the message, this is the address # to send the copy to. # # See: http://www.mail-archive.com/faq.html#newlist recipient: archive@mail-archive.com mailman-3.1.1/src/mailman/rules/0000775000175000017500000000000013204154702017607 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/any.py0000664000175000017500000000231113066532160020751 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Check if any previous rules have matched.""" from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class Any: """Look for any previous rule match.""" name = 'any' description = _('Look for any previous rule hit.') record = False def check(self, mlist, msg, msgdata): """See `IRule`.""" return len(msgdata.get('rule_hits', [])) > 0 mailman-3.1.1/src/mailman/rules/truth.py0000664000175000017500000000223413066532160021334 0ustar maxkingmaxking00000000000000# Copyright (C) 2008-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """A rule which always matches.""" from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class Truth: """Look for any previous rule match.""" name = 'truth' description = _('A rule which always matches.') record = False def check(self, mlist, msg, msgdata): """See `IRule`.""" return True mailman-3.1.1/src/mailman/rules/data/0000775000175000017500000000000013204154702020520 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/data/public_suffix_list.dat0000664000175000017500000056706413066532160025135 0ustar maxkingmaxking00000000000000// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat, // rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported. // Instructions on pulling and using this list can be found at https://publicsuffix.org/list/. // ===BEGIN ICANN DOMAINS=== // ac : https://en.wikipedia.org/wiki/.ac ac com.ac edu.ac gov.ac net.ac mil.ac org.ac // ad : https://en.wikipedia.org/wiki/.ad ad nom.ad // ae : https://en.wikipedia.org/wiki/.ae // see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php ae co.ae net.ae org.ae sch.ae ac.ae gov.ae mil.ae // aero : see https://www.information.aero/index.php?id=66 aero accident-investigation.aero accident-prevention.aero aerobatic.aero aeroclub.aero aerodrome.aero agents.aero aircraft.aero airline.aero airport.aero air-surveillance.aero airtraffic.aero air-traffic-control.aero ambulance.aero amusement.aero association.aero author.aero ballooning.aero broker.aero caa.aero cargo.aero catering.aero certification.aero championship.aero charter.aero civilaviation.aero club.aero conference.aero consultant.aero consulting.aero control.aero council.aero crew.aero design.aero dgca.aero educator.aero emergency.aero engine.aero engineer.aero entertainment.aero equipment.aero exchange.aero express.aero federation.aero flight.aero freight.aero fuel.aero gliding.aero government.aero groundhandling.aero group.aero hanggliding.aero homebuilt.aero insurance.aero journal.aero journalist.aero leasing.aero logistics.aero magazine.aero maintenance.aero media.aero microlight.aero modelling.aero navigation.aero parachuting.aero paragliding.aero passenger-association.aero pilot.aero press.aero production.aero recreation.aero repbody.aero res.aero research.aero rotorcraft.aero safety.aero scientist.aero services.aero show.aero skydiving.aero software.aero student.aero trader.aero trading.aero trainer.aero union.aero workinggroup.aero works.aero // af : http://www.nic.af/help.jsp af gov.af com.af org.af net.af edu.af // ag : http://www.nic.ag/prices.htm ag com.ag org.ag net.ag co.ag nom.ag // ai : http://nic.com.ai/ ai off.ai com.ai net.ai org.ai // al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31 al com.al edu.al gov.al mil.al net.al org.al // am : https://en.wikipedia.org/wiki/.am am // ao : https://en.wikipedia.org/wiki/.ao // http://www.dns.ao/REGISTR.DOC ao ed.ao gv.ao og.ao co.ao pb.ao it.ao // aq : https://en.wikipedia.org/wiki/.aq aq // ar : https://nic.ar/normativa-vigente.xhtml ar com.ar edu.ar gob.ar gov.ar int.ar mil.ar net.ar org.ar tur.ar // arpa : https://en.wikipedia.org/wiki/.arpa // Confirmed by registry 2008-06-18 arpa e164.arpa in-addr.arpa ip6.arpa iris.arpa uri.arpa urn.arpa // as : https://en.wikipedia.org/wiki/.as as gov.as // asia : https://en.wikipedia.org/wiki/.asia asia // at : https://en.wikipedia.org/wiki/.at // Confirmed by registry 2008-06-17 at ac.at co.at gv.at or.at // au : https://en.wikipedia.org/wiki/.au // http://www.auda.org.au/ au // 2LDs com.au net.au org.au edu.au gov.au asn.au id.au // Historic 2LDs (closed to new registration, but sites still exist) info.au conf.au oz.au // CGDNs - http://www.cgdn.org.au/ act.au nsw.au nt.au qld.au sa.au tas.au vic.au wa.au // 3LDs act.edu.au nsw.edu.au nt.edu.au qld.edu.au sa.edu.au tas.edu.au vic.edu.au wa.edu.au // act.gov.au Bug 984824 - Removed at request of Greg Tankard // nsw.gov.au Bug 547985 - Removed at request of // nt.gov.au Bug 940478 - Removed at request of Greg Connors qld.gov.au sa.gov.au tas.gov.au vic.gov.au wa.gov.au // aw : https://en.wikipedia.org/wiki/.aw aw com.aw // ax : https://en.wikipedia.org/wiki/.ax ax // az : https://en.wikipedia.org/wiki/.az az com.az net.az int.az gov.az org.az edu.az info.az pp.az mil.az name.az pro.az biz.az // ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf ba com.ba edu.ba gov.ba mil.ba net.ba org.ba // bb : https://en.wikipedia.org/wiki/.bb bb biz.bb co.bb com.bb edu.bb gov.bb info.bb net.bb org.bb store.bb tv.bb // bd : https://en.wikipedia.org/wiki/.bd *.bd // be : https://en.wikipedia.org/wiki/.be // Confirmed by registry 2008-06-08 be ac.be // bf : https://en.wikipedia.org/wiki/.bf bf gov.bf // bg : https://en.wikipedia.org/wiki/.bg // https://www.register.bg/user/static/rules/en/index.html bg a.bg b.bg c.bg d.bg e.bg f.bg g.bg h.bg i.bg j.bg k.bg l.bg m.bg n.bg o.bg p.bg q.bg r.bg s.bg t.bg u.bg v.bg w.bg x.bg y.bg z.bg 0.bg 1.bg 2.bg 3.bg 4.bg 5.bg 6.bg 7.bg 8.bg 9.bg // bh : https://en.wikipedia.org/wiki/.bh bh com.bh edu.bh net.bh org.bh gov.bh // bi : https://en.wikipedia.org/wiki/.bi // http://whois.nic.bi/ bi co.bi com.bi edu.bi or.bi org.bi // biz : https://en.wikipedia.org/wiki/.biz biz // bj : https://en.wikipedia.org/wiki/.bj bj asso.bj barreau.bj gouv.bj // bm : http://www.bermudanic.bm/dnr-text.txt bm com.bm edu.bm gov.bm net.bm org.bm // bn : https://en.wikipedia.org/wiki/.bn *.bn // bo : http://www.nic.bo/ bo com.bo edu.bo gov.bo gob.bo int.bo org.bo net.bo mil.bo tv.bo // br : http://registro.br/dominio/categoria.html // Submitted by registry br adm.br adv.br agr.br am.br arq.br art.br ato.br b.br bio.br blog.br bmd.br cim.br cng.br cnt.br com.br coop.br ecn.br eco.br edu.br emp.br eng.br esp.br etc.br eti.br far.br flog.br fm.br fnd.br fot.br fst.br g12.br ggf.br gov.br imb.br ind.br inf.br jor.br jus.br leg.br lel.br mat.br med.br mil.br mp.br mus.br net.br *.nom.br not.br ntr.br odo.br org.br ppg.br pro.br psc.br psi.br qsl.br radio.br rec.br slg.br srv.br taxi.br teo.br tmp.br trd.br tur.br tv.br vet.br vlog.br wiki.br zlg.br // bs : http://www.nic.bs/rules.html bs com.bs net.bs org.bs edu.bs gov.bs // bt : https://en.wikipedia.org/wiki/.bt bt com.bt edu.bt gov.bt net.bt org.bt // bv : No registrations at this time. // Submitted by registry bv // bw : https://en.wikipedia.org/wiki/.bw // http://www.gobin.info/domainname/bw.doc // list of other 2nd level tlds ? bw co.bw org.bw // by : https://en.wikipedia.org/wiki/.by // http://tld.by/rules_2006_en.html // list of other 2nd level tlds ? by gov.by mil.by // Official information does not indicate that com.by is a reserved // second-level domain, but it's being used as one (see www.google.com.by and // www.yahoo.com.by, for example), so we list it here for safety's sake. com.by // http://hoster.by/ of.by // bz : https://en.wikipedia.org/wiki/.bz // http://www.belizenic.bz/ bz com.bz net.bz org.bz edu.bz gov.bz // ca : https://en.wikipedia.org/wiki/.ca ca // ca geographical names ab.ca bc.ca mb.ca nb.ca nf.ca nl.ca ns.ca nt.ca nu.ca on.ca pe.ca qc.ca sk.ca yk.ca // gc.ca: https://en.wikipedia.org/wiki/.gc.ca // see also: http://registry.gc.ca/en/SubdomainFAQ gc.ca // cat : https://en.wikipedia.org/wiki/.cat cat // cc : https://en.wikipedia.org/wiki/.cc cc // cd : https://en.wikipedia.org/wiki/.cd // see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1 cd gov.cd // cf : https://en.wikipedia.org/wiki/.cf cf // cg : https://en.wikipedia.org/wiki/.cg cg // ch : https://en.wikipedia.org/wiki/.ch ch // ci : https://en.wikipedia.org/wiki/.ci // http://www.nic.ci/index.php?page=charte ci org.ci or.ci com.ci co.ci edu.ci ed.ci ac.ci net.ci go.ci asso.ci aéroport.ci int.ci presse.ci md.ci gouv.ci // ck : https://en.wikipedia.org/wiki/.ck *.ck !www.ck // cl : https://en.wikipedia.org/wiki/.cl cl gov.cl gob.cl co.cl mil.cl // cm : https://en.wikipedia.org/wiki/.cm plus bug 981927 cm co.cm com.cm gov.cm net.cm // cn : https://en.wikipedia.org/wiki/.cn // Submitted by registry cn ac.cn com.cn edu.cn gov.cn net.cn org.cn mil.cn 公司.cn 网络.cn 網絡.cn // cn geographic names ah.cn bj.cn cq.cn fj.cn gd.cn gs.cn gz.cn gx.cn ha.cn hb.cn he.cn hi.cn hl.cn hn.cn jl.cn js.cn jx.cn ln.cn nm.cn nx.cn qh.cn sc.cn sd.cn sh.cn sn.cn sx.cn tj.cn xj.cn xz.cn yn.cn zj.cn hk.cn mo.cn tw.cn // co : https://en.wikipedia.org/wiki/.co // Submitted by registry co arts.co com.co edu.co firm.co gov.co info.co int.co mil.co net.co nom.co org.co rec.co web.co // com : https://en.wikipedia.org/wiki/.com com // coop : https://en.wikipedia.org/wiki/.coop coop // cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do cr ac.cr co.cr ed.cr fi.cr go.cr or.cr sa.cr // cu : https://en.wikipedia.org/wiki/.cu cu com.cu edu.cu org.cu net.cu gov.cu inf.cu // cv : https://en.wikipedia.org/wiki/.cv cv // cw : http://www.una.cw/cw_registry/ // Confirmed by registry 2013-03-26 cw com.cw edu.cw net.cw org.cw // cx : https://en.wikipedia.org/wiki/.cx // list of other 2nd level tlds ? cx gov.cx // cy : http://www.nic.cy/ // Submitted by registry Panayiotou Fotia cy ac.cy biz.cy com.cy ekloges.cy gov.cy ltd.cy name.cy net.cy org.cy parliament.cy press.cy pro.cy tm.cy // cz : https://en.wikipedia.org/wiki/.cz cz // de : https://en.wikipedia.org/wiki/.de // Confirmed by registry (with technical // reservations) 2008-07-01 de // dj : https://en.wikipedia.org/wiki/.dj dj // dk : https://en.wikipedia.org/wiki/.dk // Confirmed by registry 2008-06-17 dk // dm : https://en.wikipedia.org/wiki/.dm dm com.dm net.dm org.dm edu.dm gov.dm // do : https://en.wikipedia.org/wiki/.do do art.do com.do edu.do gob.do gov.do mil.do net.do org.do sld.do web.do // dz : https://en.wikipedia.org/wiki/.dz dz com.dz org.dz net.dz gov.dz edu.dz asso.dz pol.dz art.dz // ec : http://www.nic.ec/reg/paso1.asp // Submitted by registry ec com.ec info.ec net.ec fin.ec k12.ec med.ec pro.ec org.ec edu.ec gov.ec gob.ec mil.ec // edu : https://en.wikipedia.org/wiki/.edu edu // ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B ee edu.ee gov.ee riik.ee lib.ee med.ee com.ee pri.ee aip.ee org.ee fie.ee // eg : https://en.wikipedia.org/wiki/.eg eg com.eg edu.eg eun.eg gov.eg mil.eg name.eg net.eg org.eg sci.eg // er : https://en.wikipedia.org/wiki/.er *.er // es : https://www.nic.es/site_ingles/ingles/dominios/index.html es com.es nom.es org.es gob.es edu.es // et : https://en.wikipedia.org/wiki/.et et com.et gov.et org.et edu.et biz.et name.et info.et net.et // eu : https://en.wikipedia.org/wiki/.eu eu // fi : https://en.wikipedia.org/wiki/.fi fi // aland.fi : https://en.wikipedia.org/wiki/.ax // This domain is being phased out in favor of .ax. As there are still many // domains under aland.fi, we still keep it on the list until aland.fi is // completely removed. // TODO: Check for updates (expected to be phased out around Q1/2009) aland.fi // fj : https://en.wikipedia.org/wiki/.fj *.fj // fk : https://en.wikipedia.org/wiki/.fk *.fk // fm : https://en.wikipedia.org/wiki/.fm fm // fo : https://en.wikipedia.org/wiki/.fo fo // fr : http://www.afnic.fr/ // domaines descriptifs : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-descriptifs fr com.fr asso.fr nom.fr prd.fr presse.fr tm.fr // domaines sectoriels : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-sectoriels aeroport.fr assedic.fr avocat.fr avoues.fr cci.fr chambagri.fr chirurgiens-dentistes.fr experts-comptables.fr geometre-expert.fr gouv.fr greta.fr huissier-justice.fr medecin.fr notaires.fr pharmacien.fr port.fr veterinaire.fr // ga : https://en.wikipedia.org/wiki/.ga ga // gb : This registry is effectively dormant // Submitted by registry gb // gd : https://en.wikipedia.org/wiki/.gd gd // ge : http://www.nic.net.ge/policy_en.pdf ge com.ge edu.ge gov.ge org.ge mil.ge net.ge pvt.ge // gf : https://en.wikipedia.org/wiki/.gf gf // gg : http://www.channelisles.net/register-domains/ // Confirmed by registry 2013-11-28 gg co.gg net.gg org.gg // gh : https://en.wikipedia.org/wiki/.gh // see also: http://www.nic.gh/reg_now.php // Although domains directly at second level are not possible at the moment, // they have been possible for some time and may come back. gh com.gh edu.gh gov.gh org.gh mil.gh // gi : http://www.nic.gi/rules.html gi com.gi ltd.gi gov.gi mod.gi edu.gi org.gi // gl : https://en.wikipedia.org/wiki/.gl // http://nic.gl gl co.gl com.gl edu.gl net.gl org.gl // gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm gm // gn : http://psg.com/dns/gn/gn.txt // Submitted by registry gn ac.gn com.gn edu.gn gov.gn org.gn net.gn // gov : https://en.wikipedia.org/wiki/.gov gov // gp : http://www.nic.gp/index.php?lang=en gp com.gp net.gp mobi.gp edu.gp org.gp asso.gp // gq : https://en.wikipedia.org/wiki/.gq gq // gr : https://grweb.ics.forth.gr/english/1617-B-2005.html // Submitted by registry gr com.gr edu.gr net.gr org.gr gov.gr // gs : https://en.wikipedia.org/wiki/.gs gs // gt : http://www.gt/politicas_de_registro.html gt com.gt edu.gt gob.gt ind.gt mil.gt net.gt org.gt // gu : http://gadao.gov.gu/registration.txt *.gu // gw : https://en.wikipedia.org/wiki/.gw gw // gy : https://en.wikipedia.org/wiki/.gy // http://registry.gy/ gy co.gy com.gy edu.gy gov.gy net.gy org.gy // hk : https://www.hkdnr.hk // Submitted by registry hk com.hk edu.hk gov.hk idv.hk net.hk org.hk 公司.hk 教育.hk 敎育.hk 政府.hk 個人.hk 个人.hk 箇人.hk 網络.hk 网络.hk 组織.hk 網絡.hk 网絡.hk 组织.hk 組織.hk 組织.hk // hm : https://en.wikipedia.org/wiki/.hm hm // hn : http://www.nic.hn/politicas/ps02,,05.html hn com.hn edu.hn org.hn net.hn mil.hn gob.hn // hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf hr iz.hr from.hr name.hr com.hr // ht : http://www.nic.ht/info/charte.cfm ht com.ht shop.ht firm.ht info.ht adult.ht net.ht pro.ht org.ht med.ht art.ht coop.ht pol.ht asso.ht edu.ht rel.ht gouv.ht perso.ht // hu : http://www.domain.hu/domain/English/sld.html // Confirmed by registry 2008-06-12 hu co.hu info.hu org.hu priv.hu sport.hu tm.hu 2000.hu agrar.hu bolt.hu casino.hu city.hu erotica.hu erotika.hu film.hu forum.hu games.hu hotel.hu ingatlan.hu jogasz.hu konyvelo.hu lakas.hu media.hu news.hu reklam.hu sex.hu shop.hu suli.hu szex.hu tozsde.hu utazas.hu video.hu // id : https://register.pandi.or.id/ id ac.id biz.id co.id desa.id go.id mil.id my.id net.id or.id sch.id web.id // ie : https://en.wikipedia.org/wiki/.ie ie gov.ie // il : http://www.isoc.org.il/domains/ il ac.il co.il gov.il idf.il k12.il muni.il net.il org.il // im : https://www.nic.im/ // Submitted by registry im ac.im co.im com.im ltd.co.im net.im org.im plc.co.im tt.im tv.im // in : https://en.wikipedia.org/wiki/.in // see also: https://registry.in/Policies // Please note, that nic.in is not an official eTLD, but used by most // government institutions. in co.in firm.in net.in org.in gen.in ind.in nic.in ac.in edu.in res.in gov.in mil.in // info : https://en.wikipedia.org/wiki/.info info // int : https://en.wikipedia.org/wiki/.int // Confirmed by registry 2008-06-18 int eu.int // io : http://www.nic.io/rules.html // list of other 2nd level tlds ? io com.io // iq : http://www.cmc.iq/english/iq/iqregister1.htm iq gov.iq edu.iq mil.iq com.iq org.iq net.iq // ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules // Also see http://www.nic.ir/Internationalized_Domain_Names // Two .ir entries added at request of , 2010-04-16 ir ac.ir co.ir gov.ir id.ir net.ir org.ir sch.ir // xn--mgba3a4f16a.ir (.ir, Persian YEH) ایران.ir // xn--mgba3a4fra.ir (.ir, Arabic YEH) ايران.ir // is : http://www.isnic.is/domain/rules.php // Confirmed by registry 2008-12-06 is net.is com.is edu.is gov.is org.is int.is // it : https://en.wikipedia.org/wiki/.it it gov.it edu.it // Reserved geo-names: // http://www.nic.it/documenti/regolamenti-e-linee-guida/regolamento-assegnazione-versione-6.0.pdf // There is also a list of reserved geo-names corresponding to Italian municipalities // http://www.nic.it/documenti/appendice-c.pdf, but it is not included here. // Regions abr.it abruzzo.it aosta-valley.it aostavalley.it bas.it basilicata.it cal.it calabria.it cam.it campania.it emilia-romagna.it emiliaromagna.it emr.it friuli-v-giulia.it friuli-ve-giulia.it friuli-vegiulia.it friuli-venezia-giulia.it friuli-veneziagiulia.it friuli-vgiulia.it friuliv-giulia.it friulive-giulia.it friulivegiulia.it friulivenezia-giulia.it friuliveneziagiulia.it friulivgiulia.it fvg.it laz.it lazio.it lig.it liguria.it lom.it lombardia.it lombardy.it lucania.it mar.it marche.it mol.it molise.it piedmont.it piemonte.it pmn.it pug.it puglia.it sar.it sardegna.it sardinia.it sic.it sicilia.it sicily.it taa.it tos.it toscana.it trentino-a-adige.it trentino-aadige.it trentino-alto-adige.it trentino-altoadige.it trentino-s-tirol.it trentino-stirol.it trentino-sud-tirol.it trentino-sudtirol.it trentino-sued-tirol.it trentino-suedtirol.it trentinoa-adige.it trentinoaadige.it trentinoalto-adige.it trentinoaltoadige.it trentinos-tirol.it trentinostirol.it trentinosud-tirol.it trentinosudtirol.it trentinosued-tirol.it trentinosuedtirol.it tuscany.it umb.it umbria.it val-d-aosta.it val-daosta.it vald-aosta.it valdaosta.it valle-aosta.it valle-d-aosta.it valle-daosta.it valleaosta.it valled-aosta.it valledaosta.it vallee-aoste.it valleeaoste.it vao.it vda.it ven.it veneto.it // Provinces ag.it agrigento.it al.it alessandria.it alto-adige.it altoadige.it an.it ancona.it andria-barletta-trani.it andria-trani-barletta.it andriabarlettatrani.it andriatranibarletta.it ao.it aosta.it aoste.it ap.it aq.it aquila.it ar.it arezzo.it ascoli-piceno.it ascolipiceno.it asti.it at.it av.it avellino.it ba.it balsan.it bari.it barletta-trani-andria.it barlettatraniandria.it belluno.it benevento.it bergamo.it bg.it bi.it biella.it bl.it bn.it bo.it bologna.it bolzano.it bozen.it br.it brescia.it brindisi.it bs.it bt.it bz.it ca.it cagliari.it caltanissetta.it campidano-medio.it campidanomedio.it campobasso.it carbonia-iglesias.it carboniaiglesias.it carrara-massa.it carraramassa.it caserta.it catania.it catanzaro.it cb.it ce.it cesena-forli.it cesenaforli.it ch.it chieti.it ci.it cl.it cn.it co.it como.it cosenza.it cr.it cremona.it crotone.it cs.it ct.it cuneo.it cz.it dell-ogliastra.it dellogliastra.it en.it enna.it fc.it fe.it fermo.it ferrara.it fg.it fi.it firenze.it florence.it fm.it foggia.it forli-cesena.it forlicesena.it fr.it frosinone.it ge.it genoa.it genova.it go.it gorizia.it gr.it grosseto.it iglesias-carbonia.it iglesiascarbonia.it im.it imperia.it is.it isernia.it kr.it la-spezia.it laquila.it laspezia.it latina.it lc.it le.it lecce.it lecco.it li.it livorno.it lo.it lodi.it lt.it lu.it lucca.it macerata.it mantova.it massa-carrara.it massacarrara.it matera.it mb.it mc.it me.it medio-campidano.it mediocampidano.it messina.it mi.it milan.it milano.it mn.it mo.it modena.it monza-brianza.it monza-e-della-brianza.it monza.it monzabrianza.it monzaebrianza.it monzaedellabrianza.it ms.it mt.it na.it naples.it napoli.it no.it novara.it nu.it nuoro.it og.it ogliastra.it olbia-tempio.it olbiatempio.it or.it oristano.it ot.it pa.it padova.it padua.it palermo.it parma.it pavia.it pc.it pd.it pe.it perugia.it pesaro-urbino.it pesarourbino.it pescara.it pg.it pi.it piacenza.it pisa.it pistoia.it pn.it po.it pordenone.it potenza.it pr.it prato.it pt.it pu.it pv.it pz.it ra.it ragusa.it ravenna.it rc.it re.it reggio-calabria.it reggio-emilia.it reggiocalabria.it reggioemilia.it rg.it ri.it rieti.it rimini.it rm.it rn.it ro.it roma.it rome.it rovigo.it sa.it salerno.it sassari.it savona.it si.it siena.it siracusa.it so.it sondrio.it sp.it sr.it ss.it suedtirol.it sv.it ta.it taranto.it te.it tempio-olbia.it tempioolbia.it teramo.it terni.it tn.it to.it torino.it tp.it tr.it trani-andria-barletta.it trani-barletta-andria.it traniandriabarletta.it tranibarlettaandria.it trapani.it trentino.it trento.it treviso.it trieste.it ts.it turin.it tv.it ud.it udine.it urbino-pesaro.it urbinopesaro.it va.it varese.it vb.it vc.it ve.it venezia.it venice.it verbania.it vercelli.it verona.it vi.it vibo-valentia.it vibovalentia.it vicenza.it viterbo.it vr.it vs.it vt.it vv.it // je : http://www.channelisles.net/register-domains/ // Confirmed by registry 2013-11-28 je co.je net.je org.je // jm : http://www.com.jm/register.html *.jm // jo : http://www.dns.jo/Registration_policy.aspx jo com.jo org.jo net.jo edu.jo sch.jo gov.jo mil.jo name.jo // jobs : https://en.wikipedia.org/wiki/.jobs jobs // jp : https://en.wikipedia.org/wiki/.jp // http://jprs.co.jp/en/jpdomain.html // Submitted by registry jp // jp organizational type names ac.jp ad.jp co.jp ed.jp go.jp gr.jp lg.jp ne.jp or.jp // jp prefecture type names aichi.jp akita.jp aomori.jp chiba.jp ehime.jp fukui.jp fukuoka.jp fukushima.jp gifu.jp gunma.jp hiroshima.jp hokkaido.jp hyogo.jp ibaraki.jp ishikawa.jp iwate.jp kagawa.jp kagoshima.jp kanagawa.jp kochi.jp kumamoto.jp kyoto.jp mie.jp miyagi.jp miyazaki.jp nagano.jp nagasaki.jp nara.jp niigata.jp oita.jp okayama.jp okinawa.jp osaka.jp saga.jp saitama.jp shiga.jp shimane.jp shizuoka.jp tochigi.jp tokushima.jp tokyo.jp tottori.jp toyama.jp wakayama.jp yamagata.jp yamaguchi.jp yamanashi.jp 栃木.jp 愛知.jp 愛媛.jp 兵庫.jp 熊本.jp 茨城.jp 北海道.jp 千葉.jp 和歌山.jp 長崎.jp 長野.jp 新潟.jp 青森.jp 静岡.jp 東京.jp 石川.jp 埼玉.jp 三重.jp 京都.jp 佐賀.jp 大分.jp 大阪.jp 奈良.jp 宮城.jp 宮崎.jp 富山.jp 山口.jp 山形.jp 山梨.jp 岩手.jp 岐阜.jp 岡山.jp 島根.jp 広島.jp 徳島.jp 沖縄.jp 滋賀.jp 神奈川.jp 福井.jp 福岡.jp 福島.jp 秋田.jp 群馬.jp 香川.jp 高知.jp 鳥取.jp 鹿児島.jp // jp geographic type names // http://jprs.jp/doc/rule/saisoku-1.html *.kawasaki.jp *.kitakyushu.jp *.kobe.jp *.nagoya.jp *.sapporo.jp *.sendai.jp *.yokohama.jp !city.kawasaki.jp !city.kitakyushu.jp !city.kobe.jp !city.nagoya.jp !city.sapporo.jp !city.sendai.jp !city.yokohama.jp // 4th level registration aisai.aichi.jp ama.aichi.jp anjo.aichi.jp asuke.aichi.jp chiryu.aichi.jp chita.aichi.jp fuso.aichi.jp gamagori.aichi.jp handa.aichi.jp hazu.aichi.jp hekinan.aichi.jp higashiura.aichi.jp ichinomiya.aichi.jp inazawa.aichi.jp inuyama.aichi.jp isshiki.aichi.jp iwakura.aichi.jp kanie.aichi.jp kariya.aichi.jp kasugai.aichi.jp kira.aichi.jp kiyosu.aichi.jp komaki.aichi.jp konan.aichi.jp kota.aichi.jp mihama.aichi.jp miyoshi.aichi.jp nishio.aichi.jp nisshin.aichi.jp obu.aichi.jp oguchi.aichi.jp oharu.aichi.jp okazaki.aichi.jp owariasahi.aichi.jp seto.aichi.jp shikatsu.aichi.jp shinshiro.aichi.jp shitara.aichi.jp tahara.aichi.jp takahama.aichi.jp tobishima.aichi.jp toei.aichi.jp togo.aichi.jp tokai.aichi.jp tokoname.aichi.jp toyoake.aichi.jp toyohashi.aichi.jp toyokawa.aichi.jp toyone.aichi.jp toyota.aichi.jp tsushima.aichi.jp yatomi.aichi.jp akita.akita.jp daisen.akita.jp fujisato.akita.jp gojome.akita.jp hachirogata.akita.jp happou.akita.jp higashinaruse.akita.jp honjo.akita.jp honjyo.akita.jp ikawa.akita.jp kamikoani.akita.jp kamioka.akita.jp katagami.akita.jp kazuno.akita.jp kitaakita.akita.jp kosaka.akita.jp kyowa.akita.jp misato.akita.jp mitane.akita.jp moriyoshi.akita.jp nikaho.akita.jp noshiro.akita.jp odate.akita.jp oga.akita.jp ogata.akita.jp semboku.akita.jp yokote.akita.jp yurihonjo.akita.jp aomori.aomori.jp gonohe.aomori.jp hachinohe.aomori.jp hashikami.aomori.jp hiranai.aomori.jp hirosaki.aomori.jp itayanagi.aomori.jp kuroishi.aomori.jp misawa.aomori.jp mutsu.aomori.jp nakadomari.aomori.jp noheji.aomori.jp oirase.aomori.jp owani.aomori.jp rokunohe.aomori.jp sannohe.aomori.jp shichinohe.aomori.jp shingo.aomori.jp takko.aomori.jp towada.aomori.jp tsugaru.aomori.jp tsuruta.aomori.jp abiko.chiba.jp asahi.chiba.jp chonan.chiba.jp chosei.chiba.jp choshi.chiba.jp chuo.chiba.jp funabashi.chiba.jp futtsu.chiba.jp hanamigawa.chiba.jp ichihara.chiba.jp ichikawa.chiba.jp ichinomiya.chiba.jp inzai.chiba.jp isumi.chiba.jp kamagaya.chiba.jp kamogawa.chiba.jp kashiwa.chiba.jp katori.chiba.jp katsuura.chiba.jp kimitsu.chiba.jp kisarazu.chiba.jp kozaki.chiba.jp kujukuri.chiba.jp kyonan.chiba.jp matsudo.chiba.jp midori.chiba.jp mihama.chiba.jp minamiboso.chiba.jp mobara.chiba.jp mutsuzawa.chiba.jp nagara.chiba.jp nagareyama.chiba.jp narashino.chiba.jp narita.chiba.jp noda.chiba.jp oamishirasato.chiba.jp omigawa.chiba.jp onjuku.chiba.jp otaki.chiba.jp sakae.chiba.jp sakura.chiba.jp shimofusa.chiba.jp shirako.chiba.jp shiroi.chiba.jp shisui.chiba.jp sodegaura.chiba.jp sosa.chiba.jp tako.chiba.jp tateyama.chiba.jp togane.chiba.jp tohnosho.chiba.jp tomisato.chiba.jp urayasu.chiba.jp yachimata.chiba.jp yachiyo.chiba.jp yokaichiba.chiba.jp yokoshibahikari.chiba.jp yotsukaido.chiba.jp ainan.ehime.jp honai.ehime.jp ikata.ehime.jp imabari.ehime.jp iyo.ehime.jp kamijima.ehime.jp kihoku.ehime.jp kumakogen.ehime.jp masaki.ehime.jp matsuno.ehime.jp matsuyama.ehime.jp namikata.ehime.jp niihama.ehime.jp ozu.ehime.jp saijo.ehime.jp seiyo.ehime.jp shikokuchuo.ehime.jp tobe.ehime.jp toon.ehime.jp uchiko.ehime.jp uwajima.ehime.jp yawatahama.ehime.jp echizen.fukui.jp eiheiji.fukui.jp fukui.fukui.jp ikeda.fukui.jp katsuyama.fukui.jp mihama.fukui.jp minamiechizen.fukui.jp obama.fukui.jp ohi.fukui.jp ono.fukui.jp sabae.fukui.jp sakai.fukui.jp takahama.fukui.jp tsuruga.fukui.jp wakasa.fukui.jp ashiya.fukuoka.jp buzen.fukuoka.jp chikugo.fukuoka.jp chikuho.fukuoka.jp chikujo.fukuoka.jp chikushino.fukuoka.jp chikuzen.fukuoka.jp chuo.fukuoka.jp dazaifu.fukuoka.jp fukuchi.fukuoka.jp hakata.fukuoka.jp higashi.fukuoka.jp hirokawa.fukuoka.jp hisayama.fukuoka.jp iizuka.fukuoka.jp inatsuki.fukuoka.jp kaho.fukuoka.jp kasuga.fukuoka.jp kasuya.fukuoka.jp kawara.fukuoka.jp keisen.fukuoka.jp koga.fukuoka.jp kurate.fukuoka.jp kurogi.fukuoka.jp kurume.fukuoka.jp minami.fukuoka.jp miyako.fukuoka.jp miyama.fukuoka.jp miyawaka.fukuoka.jp mizumaki.fukuoka.jp munakata.fukuoka.jp nakagawa.fukuoka.jp nakama.fukuoka.jp nishi.fukuoka.jp nogata.fukuoka.jp ogori.fukuoka.jp okagaki.fukuoka.jp okawa.fukuoka.jp oki.fukuoka.jp omuta.fukuoka.jp onga.fukuoka.jp onojo.fukuoka.jp oto.fukuoka.jp saigawa.fukuoka.jp sasaguri.fukuoka.jp shingu.fukuoka.jp shinyoshitomi.fukuoka.jp shonai.fukuoka.jp soeda.fukuoka.jp sue.fukuoka.jp tachiarai.fukuoka.jp tagawa.fukuoka.jp takata.fukuoka.jp toho.fukuoka.jp toyotsu.fukuoka.jp tsuiki.fukuoka.jp ukiha.fukuoka.jp umi.fukuoka.jp usui.fukuoka.jp yamada.fukuoka.jp yame.fukuoka.jp yanagawa.fukuoka.jp yukuhashi.fukuoka.jp aizubange.fukushima.jp aizumisato.fukushima.jp aizuwakamatsu.fukushima.jp asakawa.fukushima.jp bandai.fukushima.jp date.fukushima.jp fukushima.fukushima.jp furudono.fukushima.jp futaba.fukushima.jp hanawa.fukushima.jp higashi.fukushima.jp hirata.fukushima.jp hirono.fukushima.jp iitate.fukushima.jp inawashiro.fukushima.jp ishikawa.fukushima.jp iwaki.fukushima.jp izumizaki.fukushima.jp kagamiishi.fukushima.jp kaneyama.fukushima.jp kawamata.fukushima.jp kitakata.fukushima.jp kitashiobara.fukushima.jp koori.fukushima.jp koriyama.fukushima.jp kunimi.fukushima.jp miharu.fukushima.jp mishima.fukushima.jp namie.fukushima.jp nango.fukushima.jp nishiaizu.fukushima.jp nishigo.fukushima.jp okuma.fukushima.jp omotego.fukushima.jp ono.fukushima.jp otama.fukushima.jp samegawa.fukushima.jp shimogo.fukushima.jp shirakawa.fukushima.jp showa.fukushima.jp soma.fukushima.jp sukagawa.fukushima.jp taishin.fukushima.jp tamakawa.fukushima.jp tanagura.fukushima.jp tenei.fukushima.jp yabuki.fukushima.jp yamato.fukushima.jp yamatsuri.fukushima.jp yanaizu.fukushima.jp yugawa.fukushima.jp anpachi.gifu.jp ena.gifu.jp gifu.gifu.jp ginan.gifu.jp godo.gifu.jp gujo.gifu.jp hashima.gifu.jp hichiso.gifu.jp hida.gifu.jp higashishirakawa.gifu.jp ibigawa.gifu.jp ikeda.gifu.jp kakamigahara.gifu.jp kani.gifu.jp kasahara.gifu.jp kasamatsu.gifu.jp kawaue.gifu.jp kitagata.gifu.jp mino.gifu.jp minokamo.gifu.jp mitake.gifu.jp mizunami.gifu.jp motosu.gifu.jp nakatsugawa.gifu.jp ogaki.gifu.jp sakahogi.gifu.jp seki.gifu.jp sekigahara.gifu.jp shirakawa.gifu.jp tajimi.gifu.jp takayama.gifu.jp tarui.gifu.jp toki.gifu.jp tomika.gifu.jp wanouchi.gifu.jp yamagata.gifu.jp yaotsu.gifu.jp yoro.gifu.jp annaka.gunma.jp chiyoda.gunma.jp fujioka.gunma.jp higashiagatsuma.gunma.jp isesaki.gunma.jp itakura.gunma.jp kanna.gunma.jp kanra.gunma.jp katashina.gunma.jp kawaba.gunma.jp kiryu.gunma.jp kusatsu.gunma.jp maebashi.gunma.jp meiwa.gunma.jp midori.gunma.jp minakami.gunma.jp naganohara.gunma.jp nakanojo.gunma.jp nanmoku.gunma.jp numata.gunma.jp oizumi.gunma.jp ora.gunma.jp ota.gunma.jp shibukawa.gunma.jp shimonita.gunma.jp shinto.gunma.jp showa.gunma.jp takasaki.gunma.jp takayama.gunma.jp tamamura.gunma.jp tatebayashi.gunma.jp tomioka.gunma.jp tsukiyono.gunma.jp tsumagoi.gunma.jp ueno.gunma.jp yoshioka.gunma.jp asaminami.hiroshima.jp daiwa.hiroshima.jp etajima.hiroshima.jp fuchu.hiroshima.jp fukuyama.hiroshima.jp hatsukaichi.hiroshima.jp higashihiroshima.hiroshima.jp hongo.hiroshima.jp jinsekikogen.hiroshima.jp kaita.hiroshima.jp kui.hiroshima.jp kumano.hiroshima.jp kure.hiroshima.jp mihara.hiroshima.jp miyoshi.hiroshima.jp naka.hiroshima.jp onomichi.hiroshima.jp osakikamijima.hiroshima.jp otake.hiroshima.jp saka.hiroshima.jp sera.hiroshima.jp seranishi.hiroshima.jp shinichi.hiroshima.jp shobara.hiroshima.jp takehara.hiroshima.jp abashiri.hokkaido.jp abira.hokkaido.jp aibetsu.hokkaido.jp akabira.hokkaido.jp akkeshi.hokkaido.jp asahikawa.hokkaido.jp ashibetsu.hokkaido.jp ashoro.hokkaido.jp assabu.hokkaido.jp atsuma.hokkaido.jp bibai.hokkaido.jp biei.hokkaido.jp bifuka.hokkaido.jp bihoro.hokkaido.jp biratori.hokkaido.jp chippubetsu.hokkaido.jp chitose.hokkaido.jp date.hokkaido.jp ebetsu.hokkaido.jp embetsu.hokkaido.jp eniwa.hokkaido.jp erimo.hokkaido.jp esan.hokkaido.jp esashi.hokkaido.jp fukagawa.hokkaido.jp fukushima.hokkaido.jp furano.hokkaido.jp furubira.hokkaido.jp haboro.hokkaido.jp hakodate.hokkaido.jp hamatonbetsu.hokkaido.jp hidaka.hokkaido.jp higashikagura.hokkaido.jp higashikawa.hokkaido.jp hiroo.hokkaido.jp hokuryu.hokkaido.jp hokuto.hokkaido.jp honbetsu.hokkaido.jp horokanai.hokkaido.jp horonobe.hokkaido.jp ikeda.hokkaido.jp imakane.hokkaido.jp ishikari.hokkaido.jp iwamizawa.hokkaido.jp iwanai.hokkaido.jp kamifurano.hokkaido.jp kamikawa.hokkaido.jp kamishihoro.hokkaido.jp kamisunagawa.hokkaido.jp kamoenai.hokkaido.jp kayabe.hokkaido.jp kembuchi.hokkaido.jp kikonai.hokkaido.jp kimobetsu.hokkaido.jp kitahiroshima.hokkaido.jp kitami.hokkaido.jp kiyosato.hokkaido.jp koshimizu.hokkaido.jp kunneppu.hokkaido.jp kuriyama.hokkaido.jp kuromatsunai.hokkaido.jp kushiro.hokkaido.jp kutchan.hokkaido.jp kyowa.hokkaido.jp mashike.hokkaido.jp matsumae.hokkaido.jp mikasa.hokkaido.jp minamifurano.hokkaido.jp mombetsu.hokkaido.jp moseushi.hokkaido.jp mukawa.hokkaido.jp muroran.hokkaido.jp naie.hokkaido.jp nakagawa.hokkaido.jp nakasatsunai.hokkaido.jp nakatombetsu.hokkaido.jp nanae.hokkaido.jp nanporo.hokkaido.jp nayoro.hokkaido.jp nemuro.hokkaido.jp niikappu.hokkaido.jp niki.hokkaido.jp nishiokoppe.hokkaido.jp noboribetsu.hokkaido.jp numata.hokkaido.jp obihiro.hokkaido.jp obira.hokkaido.jp oketo.hokkaido.jp okoppe.hokkaido.jp otaru.hokkaido.jp otobe.hokkaido.jp otofuke.hokkaido.jp otoineppu.hokkaido.jp oumu.hokkaido.jp ozora.hokkaido.jp pippu.hokkaido.jp rankoshi.hokkaido.jp rebun.hokkaido.jp rikubetsu.hokkaido.jp rishiri.hokkaido.jp rishirifuji.hokkaido.jp saroma.hokkaido.jp sarufutsu.hokkaido.jp shakotan.hokkaido.jp shari.hokkaido.jp shibecha.hokkaido.jp shibetsu.hokkaido.jp shikabe.hokkaido.jp shikaoi.hokkaido.jp shimamaki.hokkaido.jp shimizu.hokkaido.jp shimokawa.hokkaido.jp shinshinotsu.hokkaido.jp shintoku.hokkaido.jp shiranuka.hokkaido.jp shiraoi.hokkaido.jp shiriuchi.hokkaido.jp sobetsu.hokkaido.jp sunagawa.hokkaido.jp taiki.hokkaido.jp takasu.hokkaido.jp takikawa.hokkaido.jp takinoue.hokkaido.jp teshikaga.hokkaido.jp tobetsu.hokkaido.jp tohma.hokkaido.jp tomakomai.hokkaido.jp tomari.hokkaido.jp toya.hokkaido.jp toyako.hokkaido.jp toyotomi.hokkaido.jp toyoura.hokkaido.jp tsubetsu.hokkaido.jp tsukigata.hokkaido.jp urakawa.hokkaido.jp urausu.hokkaido.jp uryu.hokkaido.jp utashinai.hokkaido.jp wakkanai.hokkaido.jp wassamu.hokkaido.jp yakumo.hokkaido.jp yoichi.hokkaido.jp aioi.hyogo.jp akashi.hyogo.jp ako.hyogo.jp amagasaki.hyogo.jp aogaki.hyogo.jp asago.hyogo.jp ashiya.hyogo.jp awaji.hyogo.jp fukusaki.hyogo.jp goshiki.hyogo.jp harima.hyogo.jp himeji.hyogo.jp ichikawa.hyogo.jp inagawa.hyogo.jp itami.hyogo.jp kakogawa.hyogo.jp kamigori.hyogo.jp kamikawa.hyogo.jp kasai.hyogo.jp kasuga.hyogo.jp kawanishi.hyogo.jp miki.hyogo.jp minamiawaji.hyogo.jp nishinomiya.hyogo.jp nishiwaki.hyogo.jp ono.hyogo.jp sanda.hyogo.jp sannan.hyogo.jp sasayama.hyogo.jp sayo.hyogo.jp shingu.hyogo.jp shinonsen.hyogo.jp shiso.hyogo.jp sumoto.hyogo.jp taishi.hyogo.jp taka.hyogo.jp takarazuka.hyogo.jp takasago.hyogo.jp takino.hyogo.jp tamba.hyogo.jp tatsuno.hyogo.jp toyooka.hyogo.jp yabu.hyogo.jp yashiro.hyogo.jp yoka.hyogo.jp yokawa.hyogo.jp ami.ibaraki.jp asahi.ibaraki.jp bando.ibaraki.jp chikusei.ibaraki.jp daigo.ibaraki.jp fujishiro.ibaraki.jp hitachi.ibaraki.jp hitachinaka.ibaraki.jp hitachiomiya.ibaraki.jp hitachiota.ibaraki.jp ibaraki.ibaraki.jp ina.ibaraki.jp inashiki.ibaraki.jp itako.ibaraki.jp iwama.ibaraki.jp joso.ibaraki.jp kamisu.ibaraki.jp kasama.ibaraki.jp kashima.ibaraki.jp kasumigaura.ibaraki.jp koga.ibaraki.jp miho.ibaraki.jp mito.ibaraki.jp moriya.ibaraki.jp naka.ibaraki.jp namegata.ibaraki.jp oarai.ibaraki.jp ogawa.ibaraki.jp omitama.ibaraki.jp ryugasaki.ibaraki.jp sakai.ibaraki.jp sakuragawa.ibaraki.jp shimodate.ibaraki.jp shimotsuma.ibaraki.jp shirosato.ibaraki.jp sowa.ibaraki.jp suifu.ibaraki.jp takahagi.ibaraki.jp tamatsukuri.ibaraki.jp tokai.ibaraki.jp tomobe.ibaraki.jp tone.ibaraki.jp toride.ibaraki.jp tsuchiura.ibaraki.jp tsukuba.ibaraki.jp uchihara.ibaraki.jp ushiku.ibaraki.jp yachiyo.ibaraki.jp yamagata.ibaraki.jp yawara.ibaraki.jp yuki.ibaraki.jp anamizu.ishikawa.jp hakui.ishikawa.jp hakusan.ishikawa.jp kaga.ishikawa.jp kahoku.ishikawa.jp kanazawa.ishikawa.jp kawakita.ishikawa.jp komatsu.ishikawa.jp nakanoto.ishikawa.jp nanao.ishikawa.jp nomi.ishikawa.jp nonoichi.ishikawa.jp noto.ishikawa.jp shika.ishikawa.jp suzu.ishikawa.jp tsubata.ishikawa.jp tsurugi.ishikawa.jp uchinada.ishikawa.jp wajima.ishikawa.jp fudai.iwate.jp fujisawa.iwate.jp hanamaki.iwate.jp hiraizumi.iwate.jp hirono.iwate.jp ichinohe.iwate.jp ichinoseki.iwate.jp iwaizumi.iwate.jp iwate.iwate.jp joboji.iwate.jp kamaishi.iwate.jp kanegasaki.iwate.jp karumai.iwate.jp kawai.iwate.jp kitakami.iwate.jp kuji.iwate.jp kunohe.iwate.jp kuzumaki.iwate.jp miyako.iwate.jp mizusawa.iwate.jp morioka.iwate.jp ninohe.iwate.jp noda.iwate.jp ofunato.iwate.jp oshu.iwate.jp otsuchi.iwate.jp rikuzentakata.iwate.jp shiwa.iwate.jp shizukuishi.iwate.jp sumita.iwate.jp tanohata.iwate.jp tono.iwate.jp yahaba.iwate.jp yamada.iwate.jp ayagawa.kagawa.jp higashikagawa.kagawa.jp kanonji.kagawa.jp kotohira.kagawa.jp manno.kagawa.jp marugame.kagawa.jp mitoyo.kagawa.jp naoshima.kagawa.jp sanuki.kagawa.jp tadotsu.kagawa.jp takamatsu.kagawa.jp tonosho.kagawa.jp uchinomi.kagawa.jp utazu.kagawa.jp zentsuji.kagawa.jp akune.kagoshima.jp amami.kagoshima.jp hioki.kagoshima.jp isa.kagoshima.jp isen.kagoshima.jp izumi.kagoshima.jp kagoshima.kagoshima.jp kanoya.kagoshima.jp kawanabe.kagoshima.jp kinko.kagoshima.jp kouyama.kagoshima.jp makurazaki.kagoshima.jp matsumoto.kagoshima.jp minamitane.kagoshima.jp nakatane.kagoshima.jp nishinoomote.kagoshima.jp satsumasendai.kagoshima.jp soo.kagoshima.jp tarumizu.kagoshima.jp yusui.kagoshima.jp aikawa.kanagawa.jp atsugi.kanagawa.jp ayase.kanagawa.jp chigasaki.kanagawa.jp ebina.kanagawa.jp fujisawa.kanagawa.jp hadano.kanagawa.jp hakone.kanagawa.jp hiratsuka.kanagawa.jp isehara.kanagawa.jp kaisei.kanagawa.jp kamakura.kanagawa.jp kiyokawa.kanagawa.jp matsuda.kanagawa.jp minamiashigara.kanagawa.jp miura.kanagawa.jp nakai.kanagawa.jp ninomiya.kanagawa.jp odawara.kanagawa.jp oi.kanagawa.jp oiso.kanagawa.jp sagamihara.kanagawa.jp samukawa.kanagawa.jp tsukui.kanagawa.jp yamakita.kanagawa.jp yamato.kanagawa.jp yokosuka.kanagawa.jp yugawara.kanagawa.jp zama.kanagawa.jp zushi.kanagawa.jp aki.kochi.jp geisei.kochi.jp hidaka.kochi.jp higashitsuno.kochi.jp ino.kochi.jp kagami.kochi.jp kami.kochi.jp kitagawa.kochi.jp kochi.kochi.jp mihara.kochi.jp motoyama.kochi.jp muroto.kochi.jp nahari.kochi.jp nakamura.kochi.jp nankoku.kochi.jp nishitosa.kochi.jp niyodogawa.kochi.jp ochi.kochi.jp okawa.kochi.jp otoyo.kochi.jp otsuki.kochi.jp sakawa.kochi.jp sukumo.kochi.jp susaki.kochi.jp tosa.kochi.jp tosashimizu.kochi.jp toyo.kochi.jp tsuno.kochi.jp umaji.kochi.jp yasuda.kochi.jp yusuhara.kochi.jp amakusa.kumamoto.jp arao.kumamoto.jp aso.kumamoto.jp choyo.kumamoto.jp gyokuto.kumamoto.jp kamiamakusa.kumamoto.jp kikuchi.kumamoto.jp kumamoto.kumamoto.jp mashiki.kumamoto.jp mifune.kumamoto.jp minamata.kumamoto.jp minamioguni.kumamoto.jp nagasu.kumamoto.jp nishihara.kumamoto.jp oguni.kumamoto.jp ozu.kumamoto.jp sumoto.kumamoto.jp takamori.kumamoto.jp uki.kumamoto.jp uto.kumamoto.jp yamaga.kumamoto.jp yamato.kumamoto.jp yatsushiro.kumamoto.jp ayabe.kyoto.jp fukuchiyama.kyoto.jp higashiyama.kyoto.jp ide.kyoto.jp ine.kyoto.jp joyo.kyoto.jp kameoka.kyoto.jp kamo.kyoto.jp kita.kyoto.jp kizu.kyoto.jp kumiyama.kyoto.jp kyotamba.kyoto.jp kyotanabe.kyoto.jp kyotango.kyoto.jp maizuru.kyoto.jp minami.kyoto.jp minamiyamashiro.kyoto.jp miyazu.kyoto.jp muko.kyoto.jp nagaokakyo.kyoto.jp nakagyo.kyoto.jp nantan.kyoto.jp oyamazaki.kyoto.jp sakyo.kyoto.jp seika.kyoto.jp tanabe.kyoto.jp uji.kyoto.jp ujitawara.kyoto.jp wazuka.kyoto.jp yamashina.kyoto.jp yawata.kyoto.jp asahi.mie.jp inabe.mie.jp ise.mie.jp kameyama.mie.jp kawagoe.mie.jp kiho.mie.jp kisosaki.mie.jp kiwa.mie.jp komono.mie.jp kumano.mie.jp kuwana.mie.jp matsusaka.mie.jp meiwa.mie.jp mihama.mie.jp minamiise.mie.jp misugi.mie.jp miyama.mie.jp nabari.mie.jp shima.mie.jp suzuka.mie.jp tado.mie.jp taiki.mie.jp taki.mie.jp tamaki.mie.jp toba.mie.jp tsu.mie.jp udono.mie.jp ureshino.mie.jp watarai.mie.jp yokkaichi.mie.jp furukawa.miyagi.jp higashimatsushima.miyagi.jp ishinomaki.miyagi.jp iwanuma.miyagi.jp kakuda.miyagi.jp kami.miyagi.jp kawasaki.miyagi.jp marumori.miyagi.jp matsushima.miyagi.jp minamisanriku.miyagi.jp misato.miyagi.jp murata.miyagi.jp natori.miyagi.jp ogawara.miyagi.jp ohira.miyagi.jp onagawa.miyagi.jp osaki.miyagi.jp rifu.miyagi.jp semine.miyagi.jp shibata.miyagi.jp shichikashuku.miyagi.jp shikama.miyagi.jp shiogama.miyagi.jp shiroishi.miyagi.jp tagajo.miyagi.jp taiwa.miyagi.jp tome.miyagi.jp tomiya.miyagi.jp wakuya.miyagi.jp watari.miyagi.jp yamamoto.miyagi.jp zao.miyagi.jp aya.miyazaki.jp ebino.miyazaki.jp gokase.miyazaki.jp hyuga.miyazaki.jp kadogawa.miyazaki.jp kawaminami.miyazaki.jp kijo.miyazaki.jp kitagawa.miyazaki.jp kitakata.miyazaki.jp kitaura.miyazaki.jp kobayashi.miyazaki.jp kunitomi.miyazaki.jp kushima.miyazaki.jp mimata.miyazaki.jp miyakonojo.miyazaki.jp miyazaki.miyazaki.jp morotsuka.miyazaki.jp nichinan.miyazaki.jp nishimera.miyazaki.jp nobeoka.miyazaki.jp saito.miyazaki.jp shiiba.miyazaki.jp shintomi.miyazaki.jp takaharu.miyazaki.jp takanabe.miyazaki.jp takazaki.miyazaki.jp tsuno.miyazaki.jp achi.nagano.jp agematsu.nagano.jp anan.nagano.jp aoki.nagano.jp asahi.nagano.jp azumino.nagano.jp chikuhoku.nagano.jp chikuma.nagano.jp chino.nagano.jp fujimi.nagano.jp hakuba.nagano.jp hara.nagano.jp hiraya.nagano.jp iida.nagano.jp iijima.nagano.jp iiyama.nagano.jp iizuna.nagano.jp ikeda.nagano.jp ikusaka.nagano.jp ina.nagano.jp karuizawa.nagano.jp kawakami.nagano.jp kiso.nagano.jp kisofukushima.nagano.jp kitaaiki.nagano.jp komagane.nagano.jp komoro.nagano.jp matsukawa.nagano.jp matsumoto.nagano.jp miasa.nagano.jp minamiaiki.nagano.jp minamimaki.nagano.jp minamiminowa.nagano.jp minowa.nagano.jp miyada.nagano.jp miyota.nagano.jp mochizuki.nagano.jp nagano.nagano.jp nagawa.nagano.jp nagiso.nagano.jp nakagawa.nagano.jp nakano.nagano.jp nozawaonsen.nagano.jp obuse.nagano.jp ogawa.nagano.jp okaya.nagano.jp omachi.nagano.jp omi.nagano.jp ookuwa.nagano.jp ooshika.nagano.jp otaki.nagano.jp otari.nagano.jp sakae.nagano.jp sakaki.nagano.jp saku.nagano.jp sakuho.nagano.jp shimosuwa.nagano.jp shinanomachi.nagano.jp shiojiri.nagano.jp suwa.nagano.jp suzaka.nagano.jp takagi.nagano.jp takamori.nagano.jp takayama.nagano.jp tateshina.nagano.jp tatsuno.nagano.jp togakushi.nagano.jp togura.nagano.jp tomi.nagano.jp ueda.nagano.jp wada.nagano.jp yamagata.nagano.jp yamanouchi.nagano.jp yasaka.nagano.jp yasuoka.nagano.jp chijiwa.nagasaki.jp futsu.nagasaki.jp goto.nagasaki.jp hasami.nagasaki.jp hirado.nagasaki.jp iki.nagasaki.jp isahaya.nagasaki.jp kawatana.nagasaki.jp kuchinotsu.nagasaki.jp matsuura.nagasaki.jp nagasaki.nagasaki.jp obama.nagasaki.jp omura.nagasaki.jp oseto.nagasaki.jp saikai.nagasaki.jp sasebo.nagasaki.jp seihi.nagasaki.jp shimabara.nagasaki.jp shinkamigoto.nagasaki.jp togitsu.nagasaki.jp tsushima.nagasaki.jp unzen.nagasaki.jp ando.nara.jp gose.nara.jp heguri.nara.jp higashiyoshino.nara.jp ikaruga.nara.jp ikoma.nara.jp kamikitayama.nara.jp kanmaki.nara.jp kashiba.nara.jp kashihara.nara.jp katsuragi.nara.jp kawai.nara.jp kawakami.nara.jp kawanishi.nara.jp koryo.nara.jp kurotaki.nara.jp mitsue.nara.jp miyake.nara.jp nara.nara.jp nosegawa.nara.jp oji.nara.jp ouda.nara.jp oyodo.nara.jp sakurai.nara.jp sango.nara.jp shimoichi.nara.jp shimokitayama.nara.jp shinjo.nara.jp soni.nara.jp takatori.nara.jp tawaramoto.nara.jp tenkawa.nara.jp tenri.nara.jp uda.nara.jp yamatokoriyama.nara.jp yamatotakada.nara.jp yamazoe.nara.jp yoshino.nara.jp aga.niigata.jp agano.niigata.jp gosen.niigata.jp itoigawa.niigata.jp izumozaki.niigata.jp joetsu.niigata.jp kamo.niigata.jp kariwa.niigata.jp kashiwazaki.niigata.jp minamiuonuma.niigata.jp mitsuke.niigata.jp muika.niigata.jp murakami.niigata.jp myoko.niigata.jp nagaoka.niigata.jp niigata.niigata.jp ojiya.niigata.jp omi.niigata.jp sado.niigata.jp sanjo.niigata.jp seiro.niigata.jp seirou.niigata.jp sekikawa.niigata.jp shibata.niigata.jp tagami.niigata.jp tainai.niigata.jp tochio.niigata.jp tokamachi.niigata.jp tsubame.niigata.jp tsunan.niigata.jp uonuma.niigata.jp yahiko.niigata.jp yoita.niigata.jp yuzawa.niigata.jp beppu.oita.jp bungoono.oita.jp bungotakada.oita.jp hasama.oita.jp hiji.oita.jp himeshima.oita.jp hita.oita.jp kamitsue.oita.jp kokonoe.oita.jp kuju.oita.jp kunisaki.oita.jp kusu.oita.jp oita.oita.jp saiki.oita.jp taketa.oita.jp tsukumi.oita.jp usa.oita.jp usuki.oita.jp yufu.oita.jp akaiwa.okayama.jp asakuchi.okayama.jp bizen.okayama.jp hayashima.okayama.jp ibara.okayama.jp kagamino.okayama.jp kasaoka.okayama.jp kibichuo.okayama.jp kumenan.okayama.jp kurashiki.okayama.jp maniwa.okayama.jp misaki.okayama.jp nagi.okayama.jp niimi.okayama.jp nishiawakura.okayama.jp okayama.okayama.jp satosho.okayama.jp setouchi.okayama.jp shinjo.okayama.jp shoo.okayama.jp soja.okayama.jp takahashi.okayama.jp tamano.okayama.jp tsuyama.okayama.jp wake.okayama.jp yakage.okayama.jp aguni.okinawa.jp ginowan.okinawa.jp ginoza.okinawa.jp gushikami.okinawa.jp haebaru.okinawa.jp higashi.okinawa.jp hirara.okinawa.jp iheya.okinawa.jp ishigaki.okinawa.jp ishikawa.okinawa.jp itoman.okinawa.jp izena.okinawa.jp kadena.okinawa.jp kin.okinawa.jp kitadaito.okinawa.jp kitanakagusuku.okinawa.jp kumejima.okinawa.jp kunigami.okinawa.jp minamidaito.okinawa.jp motobu.okinawa.jp nago.okinawa.jp naha.okinawa.jp nakagusuku.okinawa.jp nakijin.okinawa.jp nanjo.okinawa.jp nishihara.okinawa.jp ogimi.okinawa.jp okinawa.okinawa.jp onna.okinawa.jp shimoji.okinawa.jp taketomi.okinawa.jp tarama.okinawa.jp tokashiki.okinawa.jp tomigusuku.okinawa.jp tonaki.okinawa.jp urasoe.okinawa.jp uruma.okinawa.jp yaese.okinawa.jp yomitan.okinawa.jp yonabaru.okinawa.jp yonaguni.okinawa.jp zamami.okinawa.jp abeno.osaka.jp chihayaakasaka.osaka.jp chuo.osaka.jp daito.osaka.jp fujiidera.osaka.jp habikino.osaka.jp hannan.osaka.jp higashiosaka.osaka.jp higashisumiyoshi.osaka.jp higashiyodogawa.osaka.jp hirakata.osaka.jp ibaraki.osaka.jp ikeda.osaka.jp izumi.osaka.jp izumiotsu.osaka.jp izumisano.osaka.jp kadoma.osaka.jp kaizuka.osaka.jp kanan.osaka.jp kashiwara.osaka.jp katano.osaka.jp kawachinagano.osaka.jp kishiwada.osaka.jp kita.osaka.jp kumatori.osaka.jp matsubara.osaka.jp minato.osaka.jp minoh.osaka.jp misaki.osaka.jp moriguchi.osaka.jp neyagawa.osaka.jp nishi.osaka.jp nose.osaka.jp osakasayama.osaka.jp sakai.osaka.jp sayama.osaka.jp sennan.osaka.jp settsu.osaka.jp shijonawate.osaka.jp shimamoto.osaka.jp suita.osaka.jp tadaoka.osaka.jp taishi.osaka.jp tajiri.osaka.jp takaishi.osaka.jp takatsuki.osaka.jp tondabayashi.osaka.jp toyonaka.osaka.jp toyono.osaka.jp yao.osaka.jp ariake.saga.jp arita.saga.jp fukudomi.saga.jp genkai.saga.jp hamatama.saga.jp hizen.saga.jp imari.saga.jp kamimine.saga.jp kanzaki.saga.jp karatsu.saga.jp kashima.saga.jp kitagata.saga.jp kitahata.saga.jp kiyama.saga.jp kouhoku.saga.jp kyuragi.saga.jp nishiarita.saga.jp ogi.saga.jp omachi.saga.jp ouchi.saga.jp saga.saga.jp shiroishi.saga.jp taku.saga.jp tara.saga.jp tosu.saga.jp yoshinogari.saga.jp arakawa.saitama.jp asaka.saitama.jp chichibu.saitama.jp fujimi.saitama.jp fujimino.saitama.jp fukaya.saitama.jp hanno.saitama.jp hanyu.saitama.jp hasuda.saitama.jp hatogaya.saitama.jp hatoyama.saitama.jp hidaka.saitama.jp higashichichibu.saitama.jp higashimatsuyama.saitama.jp honjo.saitama.jp ina.saitama.jp iruma.saitama.jp iwatsuki.saitama.jp kamiizumi.saitama.jp kamikawa.saitama.jp kamisato.saitama.jp kasukabe.saitama.jp kawagoe.saitama.jp kawaguchi.saitama.jp kawajima.saitama.jp kazo.saitama.jp kitamoto.saitama.jp koshigaya.saitama.jp kounosu.saitama.jp kuki.saitama.jp kumagaya.saitama.jp matsubushi.saitama.jp minano.saitama.jp misato.saitama.jp miyashiro.saitama.jp miyoshi.saitama.jp moroyama.saitama.jp nagatoro.saitama.jp namegawa.saitama.jp niiza.saitama.jp ogano.saitama.jp ogawa.saitama.jp ogose.saitama.jp okegawa.saitama.jp omiya.saitama.jp otaki.saitama.jp ranzan.saitama.jp ryokami.saitama.jp saitama.saitama.jp sakado.saitama.jp satte.saitama.jp sayama.saitama.jp shiki.saitama.jp shiraoka.saitama.jp soka.saitama.jp sugito.saitama.jp toda.saitama.jp tokigawa.saitama.jp tokorozawa.saitama.jp tsurugashima.saitama.jp urawa.saitama.jp warabi.saitama.jp yashio.saitama.jp yokoze.saitama.jp yono.saitama.jp yorii.saitama.jp yoshida.saitama.jp yoshikawa.saitama.jp yoshimi.saitama.jp aisho.shiga.jp gamo.shiga.jp higashiomi.shiga.jp hikone.shiga.jp koka.shiga.jp konan.shiga.jp kosei.shiga.jp koto.shiga.jp kusatsu.shiga.jp maibara.shiga.jp moriyama.shiga.jp nagahama.shiga.jp nishiazai.shiga.jp notogawa.shiga.jp omihachiman.shiga.jp otsu.shiga.jp ritto.shiga.jp ryuoh.shiga.jp takashima.shiga.jp takatsuki.shiga.jp torahime.shiga.jp toyosato.shiga.jp yasu.shiga.jp akagi.shimane.jp ama.shimane.jp gotsu.shimane.jp hamada.shimane.jp higashiizumo.shimane.jp hikawa.shimane.jp hikimi.shimane.jp izumo.shimane.jp kakinoki.shimane.jp masuda.shimane.jp matsue.shimane.jp misato.shimane.jp nishinoshima.shimane.jp ohda.shimane.jp okinoshima.shimane.jp okuizumo.shimane.jp shimane.shimane.jp tamayu.shimane.jp tsuwano.shimane.jp unnan.shimane.jp yakumo.shimane.jp yasugi.shimane.jp yatsuka.shimane.jp arai.shizuoka.jp atami.shizuoka.jp fuji.shizuoka.jp fujieda.shizuoka.jp fujikawa.shizuoka.jp fujinomiya.shizuoka.jp fukuroi.shizuoka.jp gotemba.shizuoka.jp haibara.shizuoka.jp hamamatsu.shizuoka.jp higashiizu.shizuoka.jp ito.shizuoka.jp iwata.shizuoka.jp izu.shizuoka.jp izunokuni.shizuoka.jp kakegawa.shizuoka.jp kannami.shizuoka.jp kawanehon.shizuoka.jp kawazu.shizuoka.jp kikugawa.shizuoka.jp kosai.shizuoka.jp makinohara.shizuoka.jp matsuzaki.shizuoka.jp minamiizu.shizuoka.jp mishima.shizuoka.jp morimachi.shizuoka.jp nishiizu.shizuoka.jp numazu.shizuoka.jp omaezaki.shizuoka.jp shimada.shizuoka.jp shimizu.shizuoka.jp shimoda.shizuoka.jp shizuoka.shizuoka.jp susono.shizuoka.jp yaizu.shizuoka.jp yoshida.shizuoka.jp ashikaga.tochigi.jp bato.tochigi.jp haga.tochigi.jp ichikai.tochigi.jp iwafune.tochigi.jp kaminokawa.tochigi.jp kanuma.tochigi.jp karasuyama.tochigi.jp kuroiso.tochigi.jp mashiko.tochigi.jp mibu.tochigi.jp moka.tochigi.jp motegi.tochigi.jp nasu.tochigi.jp nasushiobara.tochigi.jp nikko.tochigi.jp nishikata.tochigi.jp nogi.tochigi.jp ohira.tochigi.jp ohtawara.tochigi.jp oyama.tochigi.jp sakura.tochigi.jp sano.tochigi.jp shimotsuke.tochigi.jp shioya.tochigi.jp takanezawa.tochigi.jp tochigi.tochigi.jp tsuga.tochigi.jp ujiie.tochigi.jp utsunomiya.tochigi.jp yaita.tochigi.jp aizumi.tokushima.jp anan.tokushima.jp ichiba.tokushima.jp itano.tokushima.jp kainan.tokushima.jp komatsushima.tokushima.jp matsushige.tokushima.jp mima.tokushima.jp minami.tokushima.jp miyoshi.tokushima.jp mugi.tokushima.jp nakagawa.tokushima.jp naruto.tokushima.jp sanagochi.tokushima.jp shishikui.tokushima.jp tokushima.tokushima.jp wajiki.tokushima.jp adachi.tokyo.jp akiruno.tokyo.jp akishima.tokyo.jp aogashima.tokyo.jp arakawa.tokyo.jp bunkyo.tokyo.jp chiyoda.tokyo.jp chofu.tokyo.jp chuo.tokyo.jp edogawa.tokyo.jp fuchu.tokyo.jp fussa.tokyo.jp hachijo.tokyo.jp hachioji.tokyo.jp hamura.tokyo.jp higashikurume.tokyo.jp higashimurayama.tokyo.jp higashiyamato.tokyo.jp hino.tokyo.jp hinode.tokyo.jp hinohara.tokyo.jp inagi.tokyo.jp itabashi.tokyo.jp katsushika.tokyo.jp kita.tokyo.jp kiyose.tokyo.jp kodaira.tokyo.jp koganei.tokyo.jp kokubunji.tokyo.jp komae.tokyo.jp koto.tokyo.jp kouzushima.tokyo.jp kunitachi.tokyo.jp machida.tokyo.jp meguro.tokyo.jp minato.tokyo.jp mitaka.tokyo.jp mizuho.tokyo.jp musashimurayama.tokyo.jp musashino.tokyo.jp nakano.tokyo.jp nerima.tokyo.jp ogasawara.tokyo.jp okutama.tokyo.jp ome.tokyo.jp oshima.tokyo.jp ota.tokyo.jp setagaya.tokyo.jp shibuya.tokyo.jp shinagawa.tokyo.jp shinjuku.tokyo.jp suginami.tokyo.jp sumida.tokyo.jp tachikawa.tokyo.jp taito.tokyo.jp tama.tokyo.jp toshima.tokyo.jp chizu.tottori.jp hino.tottori.jp kawahara.tottori.jp koge.tottori.jp kotoura.tottori.jp misasa.tottori.jp nanbu.tottori.jp nichinan.tottori.jp sakaiminato.tottori.jp tottori.tottori.jp wakasa.tottori.jp yazu.tottori.jp yonago.tottori.jp asahi.toyama.jp fuchu.toyama.jp fukumitsu.toyama.jp funahashi.toyama.jp himi.toyama.jp imizu.toyama.jp inami.toyama.jp johana.toyama.jp kamiichi.toyama.jp kurobe.toyama.jp nakaniikawa.toyama.jp namerikawa.toyama.jp nanto.toyama.jp nyuzen.toyama.jp oyabe.toyama.jp taira.toyama.jp takaoka.toyama.jp tateyama.toyama.jp toga.toyama.jp tonami.toyama.jp toyama.toyama.jp unazuki.toyama.jp uozu.toyama.jp yamada.toyama.jp arida.wakayama.jp aridagawa.wakayama.jp gobo.wakayama.jp hashimoto.wakayama.jp hidaka.wakayama.jp hirogawa.wakayama.jp inami.wakayama.jp iwade.wakayama.jp kainan.wakayama.jp kamitonda.wakayama.jp katsuragi.wakayama.jp kimino.wakayama.jp kinokawa.wakayama.jp kitayama.wakayama.jp koya.wakayama.jp koza.wakayama.jp kozagawa.wakayama.jp kudoyama.wakayama.jp kushimoto.wakayama.jp mihama.wakayama.jp misato.wakayama.jp nachikatsuura.wakayama.jp shingu.wakayama.jp shirahama.wakayama.jp taiji.wakayama.jp tanabe.wakayama.jp wakayama.wakayama.jp yuasa.wakayama.jp yura.wakayama.jp asahi.yamagata.jp funagata.yamagata.jp higashine.yamagata.jp iide.yamagata.jp kahoku.yamagata.jp kaminoyama.yamagata.jp kaneyama.yamagata.jp kawanishi.yamagata.jp mamurogawa.yamagata.jp mikawa.yamagata.jp murayama.yamagata.jp nagai.yamagata.jp nakayama.yamagata.jp nanyo.yamagata.jp nishikawa.yamagata.jp obanazawa.yamagata.jp oe.yamagata.jp oguni.yamagata.jp ohkura.yamagata.jp oishida.yamagata.jp sagae.yamagata.jp sakata.yamagata.jp sakegawa.yamagata.jp shinjo.yamagata.jp shirataka.yamagata.jp shonai.yamagata.jp takahata.yamagata.jp tendo.yamagata.jp tozawa.yamagata.jp tsuruoka.yamagata.jp yamagata.yamagata.jp yamanobe.yamagata.jp yonezawa.yamagata.jp yuza.yamagata.jp abu.yamaguchi.jp hagi.yamaguchi.jp hikari.yamaguchi.jp hofu.yamaguchi.jp iwakuni.yamaguchi.jp kudamatsu.yamaguchi.jp mitou.yamaguchi.jp nagato.yamaguchi.jp oshima.yamaguchi.jp shimonoseki.yamaguchi.jp shunan.yamaguchi.jp tabuse.yamaguchi.jp tokuyama.yamaguchi.jp toyota.yamaguchi.jp ube.yamaguchi.jp yuu.yamaguchi.jp chuo.yamanashi.jp doshi.yamanashi.jp fuefuki.yamanashi.jp fujikawa.yamanashi.jp fujikawaguchiko.yamanashi.jp fujiyoshida.yamanashi.jp hayakawa.yamanashi.jp hokuto.yamanashi.jp ichikawamisato.yamanashi.jp kai.yamanashi.jp kofu.yamanashi.jp koshu.yamanashi.jp kosuge.yamanashi.jp minami-alps.yamanashi.jp minobu.yamanashi.jp nakamichi.yamanashi.jp nanbu.yamanashi.jp narusawa.yamanashi.jp nirasaki.yamanashi.jp nishikatsura.yamanashi.jp oshino.yamanashi.jp otsuki.yamanashi.jp showa.yamanashi.jp tabayama.yamanashi.jp tsuru.yamanashi.jp uenohara.yamanashi.jp yamanakako.yamanashi.jp yamanashi.yamanashi.jp // ke : http://www.kenic.or.ke/index.php?option=com_content&task=view&id=117&Itemid=145 *.ke // kg : http://www.domain.kg/dmn_n.html kg org.kg net.kg com.kg edu.kg gov.kg mil.kg // kh : http://www.mptc.gov.kh/dns_registration.htm *.kh // ki : http://www.ki/dns/index.html ki edu.ki biz.ki net.ki org.ki gov.ki info.ki com.ki // km : https://en.wikipedia.org/wiki/.km // http://www.domaine.km/documents/charte.doc km org.km nom.km gov.km prd.km tm.km edu.km mil.km ass.km com.km // These are only mentioned as proposed suggestions at domaine.km, but // https://en.wikipedia.org/wiki/.km says they're available for registration: coop.km asso.km presse.km medecin.km notaires.km pharmaciens.km veterinaire.km gouv.km // kn : https://en.wikipedia.org/wiki/.kn // http://www.dot.kn/domainRules.html kn net.kn org.kn edu.kn gov.kn // kp : http://www.kcce.kp/en_index.php kp com.kp edu.kp gov.kp org.kp rep.kp tra.kp // kr : https://en.wikipedia.org/wiki/.kr // see also: http://domain.nida.or.kr/eng/registration.jsp kr ac.kr co.kr es.kr go.kr hs.kr kg.kr mil.kr ms.kr ne.kr or.kr pe.kr re.kr sc.kr // kr geographical names busan.kr chungbuk.kr chungnam.kr daegu.kr daejeon.kr gangwon.kr gwangju.kr gyeongbuk.kr gyeonggi.kr gyeongnam.kr incheon.kr jeju.kr jeonbuk.kr jeonnam.kr seoul.kr ulsan.kr // kw : https://en.wikipedia.org/wiki/.kw *.kw // ky : http://www.icta.ky/da_ky_reg_dom.php // Confirmed by registry 2008-06-17 ky edu.ky gov.ky com.ky org.ky net.ky // kz : https://en.wikipedia.org/wiki/.kz // see also: http://www.nic.kz/rules/index.jsp kz org.kz edu.kz net.kz gov.kz mil.kz com.kz // la : https://en.wikipedia.org/wiki/.la // Submitted by registry la int.la net.la info.la edu.la gov.la per.la com.la org.la // lb : https://en.wikipedia.org/wiki/.lb // Submitted by registry lb com.lb edu.lb gov.lb net.lb org.lb // lc : https://en.wikipedia.org/wiki/.lc // see also: http://www.nic.lc/rules.htm lc com.lc net.lc co.lc org.lc edu.lc gov.lc // li : https://en.wikipedia.org/wiki/.li li // lk : http://www.nic.lk/seclevpr.html lk gov.lk sch.lk net.lk int.lk com.lk org.lk edu.lk ngo.lk soc.lk web.lk ltd.lk assn.lk grp.lk hotel.lk ac.lk // lr : http://psg.com/dns/lr/lr.txt // Submitted by registry lr com.lr edu.lr gov.lr org.lr net.lr // ls : https://en.wikipedia.org/wiki/.ls ls co.ls org.ls // lt : https://en.wikipedia.org/wiki/.lt lt // gov.lt : http://www.gov.lt/index_en.php gov.lt // lu : http://www.dns.lu/en/ lu // lv : http://www.nic.lv/DNS/En/generic.php lv com.lv edu.lv gov.lv org.lv mil.lv id.lv net.lv asn.lv conf.lv // ly : http://www.nic.ly/regulations.php ly com.ly net.ly gov.ly plc.ly edu.ly sch.ly med.ly org.ly id.ly // ma : https://en.wikipedia.org/wiki/.ma // http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf ma co.ma net.ma gov.ma org.ma ac.ma press.ma // mc : http://www.nic.mc/ mc tm.mc asso.mc // md : https://en.wikipedia.org/wiki/.md md // me : https://en.wikipedia.org/wiki/.me me co.me net.me org.me edu.me ac.me gov.me its.me priv.me // mg : http://nic.mg/nicmg/?page_id=39 mg org.mg nom.mg gov.mg prd.mg tm.mg edu.mg mil.mg com.mg co.mg // mh : https://en.wikipedia.org/wiki/.mh mh // mil : https://en.wikipedia.org/wiki/.mil mil // mk : https://en.wikipedia.org/wiki/.mk // see also: http://dns.marnet.net.mk/postapka.php mk com.mk org.mk net.mk edu.mk gov.mk inf.mk name.mk // ml : http://www.gobin.info/domainname/ml-template.doc // see also: https://en.wikipedia.org/wiki/.ml ml com.ml edu.ml gouv.ml gov.ml net.ml org.ml presse.ml // mm : https://en.wikipedia.org/wiki/.mm *.mm // mn : https://en.wikipedia.org/wiki/.mn mn gov.mn edu.mn org.mn // mo : http://www.monic.net.mo/ mo com.mo net.mo org.mo edu.mo gov.mo // mobi : https://en.wikipedia.org/wiki/.mobi mobi // mp : http://www.dot.mp/ // Confirmed by registry 2008-06-17 mp // mq : https://en.wikipedia.org/wiki/.mq mq // mr : https://en.wikipedia.org/wiki/.mr mr gov.mr // ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf ms com.ms edu.ms gov.ms net.ms org.ms // mt : https://www.nic.org.mt/go/policy // Submitted by registry mt com.mt edu.mt net.mt org.mt // mu : https://en.wikipedia.org/wiki/.mu mu com.mu net.mu org.mu gov.mu ac.mu co.mu or.mu // museum : http://about.museum/naming/ // http://index.museum/ museum academy.museum agriculture.museum air.museum airguard.museum alabama.museum alaska.museum amber.museum ambulance.museum american.museum americana.museum americanantiques.museum americanart.museum amsterdam.museum and.museum annefrank.museum anthro.museum anthropology.museum antiques.museum aquarium.museum arboretum.museum archaeological.museum archaeology.museum architecture.museum art.museum artanddesign.museum artcenter.museum artdeco.museum arteducation.museum artgallery.museum arts.museum artsandcrafts.museum asmatart.museum assassination.museum assisi.museum association.museum astronomy.museum atlanta.museum austin.museum australia.museum automotive.museum aviation.museum axis.museum badajoz.museum baghdad.museum bahn.museum bale.museum baltimore.museum barcelona.museum baseball.museum basel.museum baths.museum bauern.museum beauxarts.museum beeldengeluid.museum bellevue.museum bergbau.museum berkeley.museum berlin.museum bern.museum bible.museum bilbao.museum bill.museum birdart.museum birthplace.museum bonn.museum boston.museum botanical.museum botanicalgarden.museum botanicgarden.museum botany.museum brandywinevalley.museum brasil.museum bristol.museum british.museum britishcolumbia.museum broadcast.museum brunel.museum brussel.museum brussels.museum bruxelles.museum building.museum burghof.museum bus.museum bushey.museum cadaques.museum california.museum cambridge.museum can.museum canada.museum capebreton.museum carrier.museum cartoonart.museum casadelamoneda.museum castle.museum castres.museum celtic.museum center.museum chattanooga.museum cheltenham.museum chesapeakebay.museum chicago.museum children.museum childrens.museum childrensgarden.museum chiropractic.museum chocolate.museum christiansburg.museum cincinnati.museum cinema.museum circus.museum civilisation.museum civilization.museum civilwar.museum clinton.museum clock.museum coal.museum coastaldefence.museum cody.museum coldwar.museum collection.museum colonialwilliamsburg.museum coloradoplateau.museum columbia.museum columbus.museum communication.museum communications.museum community.museum computer.museum computerhistory.museum comunicações.museum contemporary.museum contemporaryart.museum convent.museum copenhagen.museum corporation.museum correios-e-telecomunicações.museum corvette.museum costume.museum countryestate.museum county.museum crafts.museum cranbrook.museum creation.museum cultural.museum culturalcenter.museum culture.museum cyber.museum cymru.museum dali.museum dallas.museum database.museum ddr.museum decorativearts.museum delaware.museum delmenhorst.museum denmark.museum depot.museum design.museum detroit.museum dinosaur.museum discovery.museum dolls.museum donostia.museum durham.museum eastafrica.museum eastcoast.museum education.museum educational.museum egyptian.museum eisenbahn.museum elburg.museum elvendrell.museum embroidery.museum encyclopedic.museum england.museum entomology.museum environment.museum environmentalconservation.museum epilepsy.museum essex.museum estate.museum ethnology.museum exeter.museum exhibition.museum family.museum farm.museum farmequipment.museum farmers.museum farmstead.museum field.museum figueres.museum filatelia.museum film.museum fineart.museum finearts.museum finland.museum flanders.museum florida.museum force.museum fortmissoula.museum fortworth.museum foundation.museum francaise.museum frankfurt.museum franziskaner.museum freemasonry.museum freiburg.museum fribourg.museum frog.museum fundacio.museum furniture.museum gallery.museum garden.museum gateway.museum geelvinck.museum gemological.museum geology.museum georgia.museum giessen.museum glas.museum glass.museum gorge.museum grandrapids.museum graz.museum guernsey.museum halloffame.museum hamburg.museum handson.museum harvestcelebration.museum hawaii.museum health.museum heimatunduhren.museum hellas.museum helsinki.museum hembygdsforbund.museum heritage.museum histoire.museum historical.museum historicalsociety.museum historichouses.museum historisch.museum historisches.museum history.museum historyofscience.museum horology.museum house.museum humanities.museum illustration.museum imageandsound.museum indian.museum indiana.museum indianapolis.museum indianmarket.museum intelligence.museum interactive.museum iraq.museum iron.museum isleofman.museum jamison.museum jefferson.museum jerusalem.museum jewelry.museum jewish.museum jewishart.museum jfk.museum journalism.museum judaica.museum judygarland.museum juedisches.museum juif.museum karate.museum karikatur.museum kids.museum koebenhavn.museum koeln.museum kunst.museum kunstsammlung.museum kunstunddesign.museum labor.museum labour.museum lajolla.museum lancashire.museum landes.museum lans.museum läns.museum larsson.museum lewismiller.museum lincoln.museum linz.museum living.museum livinghistory.museum localhistory.museum london.museum losangeles.museum louvre.museum loyalist.museum lucerne.museum luxembourg.museum luzern.museum mad.museum madrid.museum mallorca.museum manchester.museum mansion.museum mansions.museum manx.museum marburg.museum maritime.museum maritimo.museum maryland.museum marylhurst.museum media.museum medical.museum medizinhistorisches.museum meeres.museum memorial.museum mesaverde.museum michigan.museum midatlantic.museum military.museum mill.museum miners.museum mining.museum minnesota.museum missile.museum missoula.museum modern.museum moma.museum money.museum monmouth.museum monticello.museum montreal.museum moscow.museum motorcycle.museum muenchen.museum muenster.museum mulhouse.museum muncie.museum museet.museum museumcenter.museum museumvereniging.museum music.museum national.museum nationalfirearms.museum nationalheritage.museum nativeamerican.museum naturalhistory.museum naturalhistorymuseum.museum naturalsciences.museum nature.museum naturhistorisches.museum natuurwetenschappen.museum naumburg.museum naval.museum nebraska.museum neues.museum newhampshire.museum newjersey.museum newmexico.museum newport.museum newspaper.museum newyork.museum niepce.museum norfolk.museum north.museum nrw.museum nuernberg.museum nuremberg.museum nyc.museum nyny.museum oceanographic.museum oceanographique.museum omaha.museum online.museum ontario.museum openair.museum oregon.museum oregontrail.museum otago.museum oxford.museum pacific.museum paderborn.museum palace.museum paleo.museum palmsprings.museum panama.museum paris.museum pasadena.museum pharmacy.museum philadelphia.museum philadelphiaarea.museum philately.museum phoenix.museum photography.museum pilots.museum pittsburgh.museum planetarium.museum plantation.museum plants.museum plaza.museum portal.museum portland.museum portlligat.museum posts-and-telecommunications.museum preservation.museum presidio.museum press.museum project.museum public.museum pubol.museum quebec.museum railroad.museum railway.museum research.museum resistance.museum riodejaneiro.museum rochester.museum rockart.museum roma.museum russia.museum saintlouis.museum salem.museum salvadordali.museum salzburg.museum sandiego.museum sanfrancisco.museum santabarbara.museum santacruz.museum santafe.museum saskatchewan.museum satx.museum savannahga.museum schlesisches.museum schoenbrunn.museum schokoladen.museum school.museum schweiz.museum science.museum scienceandhistory.museum scienceandindustry.museum sciencecenter.museum sciencecenters.museum science-fiction.museum sciencehistory.museum sciences.museum sciencesnaturelles.museum scotland.museum seaport.museum settlement.museum settlers.museum shell.museum sherbrooke.museum sibenik.museum silk.museum ski.museum skole.museum society.museum sologne.museum soundandvision.museum southcarolina.museum southwest.museum space.museum spy.museum square.museum stadt.museum stalbans.museum starnberg.museum state.museum stateofdelaware.museum station.museum steam.museum steiermark.museum stjohn.museum stockholm.museum stpetersburg.museum stuttgart.museum suisse.museum surgeonshall.museum surrey.museum svizzera.museum sweden.museum sydney.museum tank.museum tcm.museum technology.museum telekommunikation.museum television.museum texas.museum textile.museum theater.museum time.museum timekeeping.museum topology.museum torino.museum touch.museum town.museum transport.museum tree.museum trolley.museum trust.museum trustee.museum uhren.museum ulm.museum undersea.museum university.museum usa.museum usantiques.museum usarts.museum uscountryestate.museum usculture.museum usdecorativearts.museum usgarden.museum ushistory.museum ushuaia.museum uslivinghistory.museum utah.museum uvic.museum valley.museum vantaa.museum versailles.museum viking.museum village.museum virginia.museum virtual.museum virtuel.museum vlaanderen.museum volkenkunde.museum wales.museum wallonie.museum war.museum washingtondc.museum watchandclock.museum watch-and-clock.museum western.museum westfalen.museum whaling.museum wildlife.museum williamsburg.museum windmill.museum workshop.museum york.museum yorkshire.museum yosemite.museum youth.museum zoological.museum zoology.museum ירושלים.museum иком.museum // mv : https://en.wikipedia.org/wiki/.mv // "mv" included because, contra Wikipedia, google.mv exists. mv aero.mv biz.mv com.mv coop.mv edu.mv gov.mv info.mv int.mv mil.mv museum.mv name.mv net.mv org.mv pro.mv // mw : http://www.registrar.mw/ mw ac.mw biz.mw co.mw com.mw coop.mw edu.mw gov.mw int.mw museum.mw net.mw org.mw // mx : http://www.nic.mx/ // Submitted by registry mx com.mx org.mx gob.mx edu.mx net.mx // my : http://www.mynic.net.my/ my com.my net.my org.my gov.my edu.my mil.my name.my // mz : http://www.uem.mz/ // Submitted by registry mz ac.mz adv.mz co.mz edu.mz gov.mz mil.mz net.mz org.mz // na : http://www.na-nic.com.na/ // http://www.info.na/domain/ na info.na pro.na name.na school.na or.na dr.na us.na mx.na ca.na in.na cc.na tv.na ws.na mobi.na co.na com.na org.na // name : has 2nd-level tlds, but there's no list of them name // nc : http://www.cctld.nc/ nc asso.nc // ne : https://en.wikipedia.org/wiki/.ne ne // net : https://en.wikipedia.org/wiki/.net net // nf : https://en.wikipedia.org/wiki/.nf nf com.nf net.nf per.nf rec.nf web.nf arts.nf firm.nf info.nf other.nf store.nf // ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds ng com.ng edu.ng gov.ng i.ng mil.ng mobi.ng name.ng net.ng org.ng sch.ng // ni : http://www.nic.ni/ ni ac.ni biz.ni co.ni com.ni edu.ni gob.ni in.ni info.ni int.ni mil.ni net.ni nom.ni org.ni web.ni // nl : https://en.wikipedia.org/wiki/.nl // https://www.sidn.nl/ // ccTLD for the Netherlands nl // BV.nl will be a registry for dutch BV's (besloten vennootschap) bv.nl // no : http://www.norid.no/regelverk/index.en.html // The Norwegian registry has declined to notify us of updates. The web pages // referenced below are the official source of the data. There is also an // announce mailing list: // https://postlister.uninett.no/sympa/info/norid-diskusjon no // Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html fhs.no vgs.no fylkesbibl.no folkebibl.no museum.no idrett.no priv.no // Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html mil.no stat.no dep.no kommune.no herad.no // no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html // counties aa.no ah.no bu.no fm.no hl.no hm.no jan-mayen.no mr.no nl.no nt.no of.no ol.no oslo.no rl.no sf.no st.no svalbard.no tm.no tr.no va.no vf.no // primary and lower secondary schools per county gs.aa.no gs.ah.no gs.bu.no gs.fm.no gs.hl.no gs.hm.no gs.jan-mayen.no gs.mr.no gs.nl.no gs.nt.no gs.of.no gs.ol.no gs.oslo.no gs.rl.no gs.sf.no gs.st.no gs.svalbard.no gs.tm.no gs.tr.no gs.va.no gs.vf.no // cities akrehamn.no åkrehamn.no algard.no ålgård.no arna.no brumunddal.no bryne.no bronnoysund.no brønnøysund.no drobak.no drøbak.no egersund.no fetsund.no floro.no florø.no fredrikstad.no hokksund.no honefoss.no hønefoss.no jessheim.no jorpeland.no jørpeland.no kirkenes.no kopervik.no krokstadelva.no langevag.no langevåg.no leirvik.no mjondalen.no mjøndalen.no mo-i-rana.no mosjoen.no mosjøen.no nesoddtangen.no orkanger.no osoyro.no osøyro.no raholt.no råholt.no sandnessjoen.no sandnessjøen.no skedsmokorset.no slattum.no spjelkavik.no stathelle.no stavern.no stjordalshalsen.no stjørdalshalsen.no tananger.no tranby.no vossevangen.no // communities afjord.no åfjord.no agdenes.no al.no ål.no alesund.no ålesund.no alstahaug.no alta.no áltá.no alaheadju.no álaheadju.no alvdal.no amli.no åmli.no amot.no åmot.no andebu.no andoy.no andøy.no andasuolo.no ardal.no årdal.no aremark.no arendal.no ås.no aseral.no åseral.no asker.no askim.no askvoll.no askoy.no askøy.no asnes.no åsnes.no audnedaln.no aukra.no aure.no aurland.no aurskog-holand.no aurskog-høland.no austevoll.no austrheim.no averoy.no averøy.no balestrand.no ballangen.no balat.no bálát.no balsfjord.no bahccavuotna.no báhccavuotna.no bamble.no bardu.no beardu.no beiarn.no bajddar.no bájddar.no baidar.no báidár.no berg.no bergen.no berlevag.no berlevåg.no bearalvahki.no bearalváhki.no bindal.no birkenes.no bjarkoy.no bjarkøy.no bjerkreim.no bjugn.no bodo.no bodø.no badaddja.no bådåddjå.no budejju.no bokn.no bremanger.no bronnoy.no brønnøy.no bygland.no bykle.no barum.no bærum.no bo.telemark.no bø.telemark.no bo.nordland.no bø.nordland.no bievat.no bievát.no bomlo.no bømlo.no batsfjord.no båtsfjord.no bahcavuotna.no báhcavuotna.no dovre.no drammen.no drangedal.no dyroy.no dyrøy.no donna.no dønna.no eid.no eidfjord.no eidsberg.no eidskog.no eidsvoll.no eigersund.no elverum.no enebakk.no engerdal.no etne.no etnedal.no evenes.no evenassi.no evenášši.no evje-og-hornnes.no farsund.no fauske.no fuossko.no fuoisku.no fedje.no fet.no finnoy.no finnøy.no fitjar.no fjaler.no fjell.no flakstad.no flatanger.no flekkefjord.no flesberg.no flora.no fla.no flå.no folldal.no forsand.no fosnes.no frei.no frogn.no froland.no frosta.no frana.no fræna.no froya.no frøya.no fusa.no fyresdal.no forde.no førde.no gamvik.no gangaviika.no gáŋgaviika.no gaular.no gausdal.no gildeskal.no gildeskål.no giske.no gjemnes.no gjerdrum.no gjerstad.no gjesdal.no gjovik.no gjøvik.no gloppen.no gol.no gran.no grane.no granvin.no gratangen.no grimstad.no grong.no kraanghke.no kråanghke.no grue.no gulen.no hadsel.no halden.no halsa.no hamar.no hamaroy.no habmer.no hábmer.no hapmir.no hápmir.no hammerfest.no hammarfeasta.no hámmárfeasta.no haram.no hareid.no harstad.no hasvik.no aknoluokta.no ákŋoluokta.no hattfjelldal.no aarborte.no haugesund.no hemne.no hemnes.no hemsedal.no heroy.more-og-romsdal.no herøy.møre-og-romsdal.no heroy.nordland.no herøy.nordland.no hitra.no hjartdal.no hjelmeland.no hobol.no hobøl.no hof.no hol.no hole.no holmestrand.no holtalen.no holtålen.no hornindal.no horten.no hurdal.no hurum.no hvaler.no hyllestad.no hagebostad.no hægebostad.no hoyanger.no høyanger.no hoylandet.no høylandet.no ha.no hå.no ibestad.no inderoy.no inderøy.no iveland.no jevnaker.no jondal.no jolster.no jølster.no karasjok.no karasjohka.no kárášjohka.no karlsoy.no galsa.no gálsá.no karmoy.no karmøy.no kautokeino.no guovdageaidnu.no klepp.no klabu.no klæbu.no kongsberg.no kongsvinger.no kragero.no kragerø.no kristiansand.no kristiansund.no krodsherad.no krødsherad.no kvalsund.no rahkkeravju.no ráhkkerávju.no kvam.no kvinesdal.no kvinnherad.no kviteseid.no kvitsoy.no kvitsøy.no kvafjord.no kvæfjord.no giehtavuoatna.no kvanangen.no kvænangen.no navuotna.no návuotna.no kafjord.no kåfjord.no gaivuotna.no gáivuotna.no larvik.no lavangen.no lavagis.no loabat.no loabát.no lebesby.no davvesiida.no leikanger.no leirfjord.no leka.no leksvik.no lenvik.no leangaviika.no leaŋgaviika.no lesja.no levanger.no lier.no lierne.no lillehammer.no lillesand.no lindesnes.no lindas.no lindås.no lom.no loppa.no lahppi.no láhppi.no lund.no lunner.no luroy.no lurøy.no luster.no lyngdal.no lyngen.no ivgu.no lardal.no lerdal.no lærdal.no lodingen.no lødingen.no lorenskog.no lørenskog.no loten.no løten.no malvik.no masoy.no måsøy.no muosat.no muosát.no mandal.no marker.no marnardal.no masfjorden.no meland.no meldal.no melhus.no meloy.no meløy.no meraker.no meråker.no moareke.no moåreke.no midsund.no midtre-gauldal.no modalen.no modum.no molde.no moskenes.no moss.no mosvik.no malselv.no målselv.no malatvuopmi.no málatvuopmi.no namdalseid.no aejrie.no namsos.no namsskogan.no naamesjevuemie.no nååmesjevuemie.no laakesvuemie.no nannestad.no narvik.no narviika.no naustdal.no nedre-eiker.no nes.akershus.no nes.buskerud.no nesna.no nesodden.no nesseby.no unjarga.no unjárga.no nesset.no nissedal.no nittedal.no nord-aurdal.no nord-fron.no nord-odal.no norddal.no nordkapp.no davvenjarga.no davvenjárga.no nordre-land.no nordreisa.no raisa.no ráisa.no nore-og-uvdal.no notodden.no naroy.no nærøy.no notteroy.no nøtterøy.no odda.no oksnes.no øksnes.no oppdal.no oppegard.no oppegård.no orkdal.no orland.no ørland.no orskog.no ørskog.no orsta.no ørsta.no os.hedmark.no os.hordaland.no osen.no osteroy.no osterøy.no ostre-toten.no østre-toten.no overhalla.no ovre-eiker.no øvre-eiker.no oyer.no øyer.no oygarden.no øygarden.no oystre-slidre.no øystre-slidre.no porsanger.no porsangu.no porsáŋgu.no porsgrunn.no radoy.no radøy.no rakkestad.no rana.no ruovat.no randaberg.no rauma.no rendalen.no rennebu.no rennesoy.no rennesøy.no rindal.no ringebu.no ringerike.no ringsaker.no rissa.no risor.no risør.no roan.no rollag.no rygge.no ralingen.no rælingen.no rodoy.no rødøy.no romskog.no rømskog.no roros.no røros.no rost.no røst.no royken.no røyken.no royrvik.no røyrvik.no rade.no råde.no salangen.no siellak.no saltdal.no salat.no sálát.no sálat.no samnanger.no sande.more-og-romsdal.no sande.møre-og-romsdal.no sande.vestfold.no sandefjord.no sandnes.no sandoy.no sandøy.no sarpsborg.no sauda.no sauherad.no sel.no selbu.no selje.no seljord.no sigdal.no siljan.no sirdal.no skaun.no skedsmo.no ski.no skien.no skiptvet.no skjervoy.no skjervøy.no skierva.no skiervá.no skjak.no skjåk.no skodje.no skanland.no skånland.no skanit.no skánit.no smola.no smøla.no snillfjord.no snasa.no snåsa.no snoasa.no snaase.no snåase.no sogndal.no sokndal.no sola.no solund.no songdalen.no sortland.no spydeberg.no stange.no stavanger.no steigen.no steinkjer.no stjordal.no stjørdal.no stokke.no stor-elvdal.no stord.no stordal.no storfjord.no omasvuotna.no strand.no stranda.no stryn.no sula.no suldal.no sund.no sunndal.no surnadal.no sveio.no svelvik.no sykkylven.no sogne.no søgne.no somna.no sømna.no sondre-land.no søndre-land.no sor-aurdal.no sør-aurdal.no sor-fron.no sør-fron.no sor-odal.no sør-odal.no sor-varanger.no sør-varanger.no matta-varjjat.no mátta-várjjat.no sorfold.no sørfold.no sorreisa.no sørreisa.no sorum.no sørum.no tana.no deatnu.no time.no tingvoll.no tinn.no tjeldsund.no dielddanuorri.no tjome.no tjøme.no tokke.no tolga.no torsken.no tranoy.no tranøy.no tromso.no tromsø.no tromsa.no romsa.no trondheim.no troandin.no trysil.no trana.no træna.no trogstad.no trøgstad.no tvedestrand.no tydal.no tynset.no tysfjord.no divtasvuodna.no divttasvuotna.no tysnes.no tysvar.no tysvær.no tonsberg.no tønsberg.no ullensaker.no ullensvang.no ulvik.no utsira.no vadso.no vadsø.no cahcesuolo.no čáhcesuolo.no vaksdal.no valle.no vang.no vanylven.no vardo.no vardø.no varggat.no várggát.no vefsn.no vaapste.no vega.no vegarshei.no vegårshei.no vennesla.no verdal.no verran.no vestby.no vestnes.no vestre-slidre.no vestre-toten.no vestvagoy.no vestvågøy.no vevelstad.no vik.no vikna.no vindafjord.no volda.no voss.no varoy.no værøy.no vagan.no vågan.no voagat.no vagsoy.no vågsøy.no vaga.no vågå.no valer.ostfold.no våler.østfold.no valer.hedmark.no våler.hedmark.no // np : http://www.mos.com.np/register.html *.np // nr : http://cenpac.net.nr/dns/index.html // Submitted by registry nr biz.nr info.nr gov.nr edu.nr org.nr net.nr com.nr // nu : https://en.wikipedia.org/wiki/.nu nu // nz : https://en.wikipedia.org/wiki/.nz // Submitted by registry nz ac.nz co.nz cri.nz geek.nz gen.nz govt.nz health.nz iwi.nz kiwi.nz maori.nz mil.nz māori.nz net.nz org.nz parliament.nz school.nz // om : https://en.wikipedia.org/wiki/.om om co.om com.om edu.om gov.om med.om museum.om net.om org.om pro.om // org : https://en.wikipedia.org/wiki/.org org // pa : http://www.nic.pa/ // Some additional second level "domains" resolve directly as hostnames, such as // pannet.pa, so we add a rule for "pa". pa ac.pa gob.pa com.pa org.pa sld.pa edu.pa net.pa ing.pa abo.pa med.pa nom.pa // pe : https://www.nic.pe/InformeFinalComision.pdf pe edu.pe gob.pe nom.pe mil.pe org.pe com.pe net.pe // pf : http://www.gobin.info/domainname/formulaire-pf.pdf pf com.pf org.pf edu.pf // pg : https://en.wikipedia.org/wiki/.pg *.pg // ph : http://www.domains.ph/FAQ2.asp // Submitted by registry ph com.ph net.ph org.ph gov.ph edu.ph ngo.ph mil.ph i.ph // pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK pk com.pk net.pk edu.pk org.pk fam.pk biz.pk web.pk gov.pk gob.pk gok.pk gon.pk gop.pk gos.pk info.pk // pl http://www.dns.pl/english/index.html // Submitted by registry pl com.pl net.pl org.pl // pl functional domains (http://www.dns.pl/english/index.html) aid.pl agro.pl atm.pl auto.pl biz.pl edu.pl gmina.pl gsm.pl info.pl mail.pl miasta.pl media.pl mil.pl nieruchomosci.pl nom.pl pc.pl powiat.pl priv.pl realestate.pl rel.pl sex.pl shop.pl sklep.pl sos.pl szkola.pl targi.pl tm.pl tourism.pl travel.pl turystyka.pl // Government domains gov.pl ap.gov.pl ic.gov.pl is.gov.pl us.gov.pl kmpsp.gov.pl kppsp.gov.pl kwpsp.gov.pl psp.gov.pl wskr.gov.pl kwp.gov.pl mw.gov.pl ug.gov.pl um.gov.pl umig.gov.pl ugim.gov.pl upow.gov.pl uw.gov.pl starostwo.gov.pl pa.gov.pl po.gov.pl psse.gov.pl pup.gov.pl rzgw.gov.pl sa.gov.pl so.gov.pl sr.gov.pl wsa.gov.pl sko.gov.pl uzs.gov.pl wiih.gov.pl winb.gov.pl pinb.gov.pl wios.gov.pl witd.gov.pl wzmiuw.gov.pl piw.gov.pl wiw.gov.pl griw.gov.pl wif.gov.pl oum.gov.pl sdn.gov.pl zp.gov.pl uppo.gov.pl mup.gov.pl wuoz.gov.pl konsulat.gov.pl oirm.gov.pl // pl regional domains (http://www.dns.pl/english/index.html) augustow.pl babia-gora.pl bedzin.pl beskidy.pl bialowieza.pl bialystok.pl bielawa.pl bieszczady.pl boleslawiec.pl bydgoszcz.pl bytom.pl cieszyn.pl czeladz.pl czest.pl dlugoleka.pl elblag.pl elk.pl glogow.pl gniezno.pl gorlice.pl grajewo.pl ilawa.pl jaworzno.pl jelenia-gora.pl jgora.pl kalisz.pl kazimierz-dolny.pl karpacz.pl kartuzy.pl kaszuby.pl katowice.pl kepno.pl ketrzyn.pl klodzko.pl kobierzyce.pl kolobrzeg.pl konin.pl konskowola.pl kutno.pl lapy.pl lebork.pl legnica.pl lezajsk.pl limanowa.pl lomza.pl lowicz.pl lubin.pl lukow.pl malbork.pl malopolska.pl mazowsze.pl mazury.pl mielec.pl mielno.pl mragowo.pl naklo.pl nowaruda.pl nysa.pl olawa.pl olecko.pl olkusz.pl olsztyn.pl opoczno.pl opole.pl ostroda.pl ostroleka.pl ostrowiec.pl ostrowwlkp.pl pila.pl pisz.pl podhale.pl podlasie.pl polkowice.pl pomorze.pl pomorskie.pl prochowice.pl pruszkow.pl przeworsk.pl pulawy.pl radom.pl rawa-maz.pl rybnik.pl rzeszow.pl sanok.pl sejny.pl slask.pl slupsk.pl sosnowiec.pl stalowa-wola.pl skoczow.pl starachowice.pl stargard.pl suwalki.pl swidnica.pl swiebodzin.pl swinoujscie.pl szczecin.pl szczytno.pl tarnobrzeg.pl tgory.pl turek.pl tychy.pl ustka.pl walbrzych.pl warmia.pl warszawa.pl waw.pl wegrow.pl wielun.pl wlocl.pl wloclawek.pl wodzislaw.pl wolomin.pl wroclaw.pl zachpomor.pl zagan.pl zarow.pl zgora.pl zgorzelec.pl // pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf pm // pn : http://www.government.pn/PnRegistry/policies.htm pn gov.pn co.pn org.pn edu.pn net.pn // post : https://en.wikipedia.org/wiki/.post post // pr : http://www.nic.pr/index.asp?f=1 pr com.pr net.pr org.pr gov.pr edu.pr isla.pr pro.pr biz.pr info.pr name.pr // these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr est.pr prof.pr ac.pr // pro : http://registry.pro/get-pro pro aaa.pro aca.pro acct.pro avocat.pro bar.pro cpa.pro eng.pro jur.pro law.pro med.pro recht.pro // ps : https://en.wikipedia.org/wiki/.ps // http://www.nic.ps/registration/policy.html#reg ps edu.ps gov.ps sec.ps plo.ps com.ps org.ps net.ps // pt : http://online.dns.pt/dns/start_dns pt net.pt gov.pt org.pt edu.pt int.pt publ.pt com.pt nome.pt // pw : https://en.wikipedia.org/wiki/.pw pw co.pw ne.pw or.pw ed.pw go.pw belau.pw // py : http://www.nic.py/pautas.html#seccion_9 // Submitted by registry py com.py coop.py edu.py gov.py mil.py net.py org.py // qa : http://domains.qa/en/ qa com.qa edu.qa gov.qa mil.qa name.qa net.qa org.qa sch.qa // re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs re asso.re com.re nom.re // ro : http://www.rotld.ro/ ro arts.ro com.ro firm.ro info.ro nom.ro nt.ro org.ro rec.ro store.ro tm.ro www.ro // rs : https://www.rnids.rs/en/domains/national-domains rs ac.rs co.rs edu.rs gov.rs in.rs org.rs // ru : https://cctld.ru/en/domains/domens_ru/reserved/ ru ac.ru edu.ru gov.ru int.ru mil.ru test.ru // rw : http://www.nic.rw/cgi-bin/policy.pl rw gov.rw net.rw edu.rw ac.rw com.rw co.rw int.rw mil.rw gouv.rw // sa : http://www.nic.net.sa/ sa com.sa net.sa org.sa gov.sa med.sa pub.sa edu.sa sch.sa // sb : http://www.sbnic.net.sb/ // Submitted by registry sb com.sb edu.sb gov.sb net.sb org.sb // sc : http://www.nic.sc/ sc com.sc gov.sc net.sc org.sc edu.sc // sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm // Submitted by registry sd com.sd net.sd org.sd edu.sd med.sd tv.sd gov.sd info.sd // se : https://en.wikipedia.org/wiki/.se // Submitted by registry se a.se ac.se b.se bd.se brand.se c.se d.se e.se f.se fh.se fhsk.se fhv.se g.se h.se i.se k.se komforb.se kommunalforbund.se komvux.se l.se lanbib.se m.se n.se naturbruksgymn.se o.se org.se p.se parti.se pp.se press.se r.se s.se t.se tm.se u.se w.se x.se y.se z.se // sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines sg com.sg net.sg org.sg gov.sg edu.sg per.sg // sh : http://www.nic.sh/registrar.html sh com.sh net.sh gov.sh org.sh mil.sh // si : https://en.wikipedia.org/wiki/.si si // sj : No registrations at this time. // Submitted by registry sj // sk : https://en.wikipedia.org/wiki/.sk // list of 2nd level domains ? sk // sl : http://www.nic.sl // Submitted by registry sl com.sl net.sl edu.sl gov.sl org.sl // sm : https://en.wikipedia.org/wiki/.sm sm // sn : https://en.wikipedia.org/wiki/.sn sn art.sn com.sn edu.sn gouv.sn org.sn perso.sn univ.sn // so : http://www.soregistry.com/ so com.so net.so org.so // sr : https://en.wikipedia.org/wiki/.sr sr // st : http://www.nic.st/html/policyrules/ st co.st com.st consulado.st edu.st embaixada.st gov.st mil.st net.st org.st principe.st saotome.st store.st // su : https://en.wikipedia.org/wiki/.su su adygeya.su arkhangelsk.su balashov.su bashkiria.su bryansk.su dagestan.su grozny.su ivanovo.su kalmykia.su kaluga.su karelia.su khakassia.su krasnodar.su kurgan.su lenug.su mordovia.su msk.su murmansk.su nalchik.su nov.su obninsk.su penza.su pokrovsk.su sochi.su spb.su togliatti.su troitsk.su tula.su tuva.su vladikavkaz.su vladimir.su vologda.su // sv : http://www.svnet.org.sv/niveldos.pdf sv com.sv edu.sv gob.sv org.sv red.sv // sx : https://en.wikipedia.org/wiki/.sx // Submitted by registry sx gov.sx // sy : https://en.wikipedia.org/wiki/.sy // see also: http://www.gobin.info/domainname/sy.doc sy edu.sy gov.sy net.sy mil.sy com.sy org.sy // sz : https://en.wikipedia.org/wiki/.sz // http://www.sispa.org.sz/ sz co.sz ac.sz org.sz // tc : https://en.wikipedia.org/wiki/.tc tc // td : https://en.wikipedia.org/wiki/.td td // tel: https://en.wikipedia.org/wiki/.tel // http://www.telnic.org/ tel // tf : https://en.wikipedia.org/wiki/.tf tf // tg : https://en.wikipedia.org/wiki/.tg // http://www.nic.tg/ tg // th : https://en.wikipedia.org/wiki/.th // Submitted by registry th ac.th co.th go.th in.th mi.th net.th or.th // tj : http://www.nic.tj/policy.html tj ac.tj biz.tj co.tj com.tj edu.tj go.tj gov.tj int.tj mil.tj name.tj net.tj nic.tj org.tj test.tj web.tj // tk : https://en.wikipedia.org/wiki/.tk tk // tl : https://en.wikipedia.org/wiki/.tl tl gov.tl // tm : http://www.nic.tm/local.html tm com.tm co.tm org.tm net.tm nom.tm gov.tm mil.tm edu.tm // tn : https://en.wikipedia.org/wiki/.tn // http://whois.ati.tn/ tn com.tn ens.tn fin.tn gov.tn ind.tn intl.tn nat.tn net.tn org.tn info.tn perso.tn tourism.tn edunet.tn rnrt.tn rns.tn rnu.tn mincom.tn agrinet.tn defense.tn turen.tn // to : https://en.wikipedia.org/wiki/.to // Submitted by registry to com.to gov.to net.to org.to edu.to mil.to // subTLDs: https://www.nic.tr/forms/eng/policies.pdf // and: https://www.nic.tr/forms/politikalar.pdf // Submitted by tr com.tr info.tr biz.tr net.tr org.tr web.tr gen.tr tv.tr av.tr dr.tr bbs.tr name.tr tel.tr gov.tr bel.tr pol.tr mil.tr k12.tr edu.tr kep.tr // Used by Northern Cyprus nc.tr // Used by government agencies of Northern Cyprus gov.nc.tr // travel : https://en.wikipedia.org/wiki/.travel travel // tt : http://www.nic.tt/ tt co.tt com.tt org.tt net.tt biz.tt info.tt pro.tt int.tt coop.tt jobs.tt mobi.tt travel.tt museum.tt aero.tt name.tt gov.tt edu.tt // tv : https://en.wikipedia.org/wiki/.tv // Not listing any 2LDs as reserved since none seem to exist in practice, // Wikipedia notwithstanding. tv // tw : https://en.wikipedia.org/wiki/.tw tw edu.tw gov.tw mil.tw com.tw net.tw org.tw idv.tw game.tw ebiz.tw club.tw 網路.tw 組織.tw 商業.tw // tz : http://www.tznic.or.tz/index.php/domains // Submitted by registry tz ac.tz co.tz go.tz hotel.tz info.tz me.tz mil.tz mobi.tz ne.tz or.tz sc.tz tv.tz // ua : https://hostmaster.ua/policy/?ua // Submitted by registry ua // ua 2LD com.ua edu.ua gov.ua in.ua net.ua org.ua // ua geographic names // https://hostmaster.ua/2ld/ cherkassy.ua cherkasy.ua chernigov.ua chernihiv.ua chernivtsi.ua chernovtsy.ua ck.ua cn.ua cr.ua crimea.ua cv.ua dn.ua dnepropetrovsk.ua dnipropetrovsk.ua dominic.ua donetsk.ua dp.ua if.ua ivano-frankivsk.ua kh.ua kharkiv.ua kharkov.ua kherson.ua khmelnitskiy.ua khmelnytskyi.ua kiev.ua kirovograd.ua km.ua kr.ua krym.ua ks.ua kv.ua kyiv.ua lg.ua lt.ua lugansk.ua lutsk.ua lv.ua lviv.ua mk.ua mykolaiv.ua nikolaev.ua od.ua odesa.ua odessa.ua pl.ua poltava.ua rivne.ua rovno.ua rv.ua sb.ua sebastopol.ua sevastopol.ua sm.ua sumy.ua te.ua ternopil.ua uz.ua uzhgorod.ua vinnica.ua vinnytsia.ua vn.ua volyn.ua yalta.ua zaporizhzhe.ua zaporizhzhia.ua zhitomir.ua zhytomyr.ua zp.ua zt.ua // ug : https://www.registry.co.ug/ ug co.ug or.ug ac.ug sc.ug go.ug ne.ug com.ug org.ug // uk : https://en.wikipedia.org/wiki/.uk // Submitted by registry uk ac.uk co.uk gov.uk ltd.uk me.uk net.uk nhs.uk org.uk plc.uk police.uk *.sch.uk // us : https://en.wikipedia.org/wiki/.us us dni.us fed.us isa.us kids.us nsn.us // us geographic names ak.us al.us ar.us as.us az.us ca.us co.us ct.us dc.us de.us fl.us ga.us gu.us hi.us ia.us id.us il.us in.us ks.us ky.us la.us ma.us md.us me.us mi.us mn.us mo.us ms.us mt.us nc.us nd.us ne.us nh.us nj.us nm.us nv.us ny.us oh.us ok.us or.us pa.us pr.us ri.us sc.us sd.us tn.us tx.us ut.us vi.us vt.us va.us wa.us wi.us wv.us wy.us // The registrar notes several more specific domains available in each state, // such as state.*.us, dst.*.us, etc., but resolution of these is somewhat // haphazard; in some states these domains resolve as addresses, while in others // only subdomains are available, or even nothing at all. We include the // most common ones where it's clear that different sites are different // entities. k12.ak.us k12.al.us k12.ar.us k12.as.us k12.az.us k12.ca.us k12.co.us k12.ct.us k12.dc.us k12.de.us k12.fl.us k12.ga.us k12.gu.us // k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login k12.ia.us k12.id.us k12.il.us k12.in.us k12.ks.us k12.ky.us k12.la.us k12.ma.us k12.md.us k12.me.us k12.mi.us k12.mn.us k12.mo.us k12.ms.us k12.mt.us k12.nc.us // k12.nd.us Bug 1028347 - Removed at request of Travis Rosso k12.ne.us k12.nh.us k12.nj.us k12.nm.us k12.nv.us k12.ny.us k12.oh.us k12.ok.us k12.or.us k12.pa.us k12.pr.us k12.ri.us k12.sc.us // k12.sd.us Bug 934131 - Removed at request of James Booze k12.tn.us k12.tx.us k12.ut.us k12.vi.us k12.vt.us k12.va.us k12.wa.us k12.wi.us // k12.wv.us Bug 947705 - Removed at request of Verne Britton k12.wy.us cc.ak.us cc.al.us cc.ar.us cc.as.us cc.az.us cc.ca.us cc.co.us cc.ct.us cc.dc.us cc.de.us cc.fl.us cc.ga.us cc.gu.us cc.hi.us cc.ia.us cc.id.us cc.il.us cc.in.us cc.ks.us cc.ky.us cc.la.us cc.ma.us cc.md.us cc.me.us cc.mi.us cc.mn.us cc.mo.us cc.ms.us cc.mt.us cc.nc.us cc.nd.us cc.ne.us cc.nh.us cc.nj.us cc.nm.us cc.nv.us cc.ny.us cc.oh.us cc.ok.us cc.or.us cc.pa.us cc.pr.us cc.ri.us cc.sc.us cc.sd.us cc.tn.us cc.tx.us cc.ut.us cc.vi.us cc.vt.us cc.va.us cc.wa.us cc.wi.us cc.wv.us cc.wy.us lib.ak.us lib.al.us lib.ar.us lib.as.us lib.az.us lib.ca.us lib.co.us lib.ct.us lib.dc.us // lib.de.us Issue #243 - Moved to Private section at request of Ed Moore lib.fl.us lib.ga.us lib.gu.us lib.hi.us lib.ia.us lib.id.us lib.il.us lib.in.us lib.ks.us lib.ky.us lib.la.us lib.ma.us lib.md.us lib.me.us lib.mi.us lib.mn.us lib.mo.us lib.ms.us lib.mt.us lib.nc.us lib.nd.us lib.ne.us lib.nh.us lib.nj.us lib.nm.us lib.nv.us lib.ny.us lib.oh.us lib.ok.us lib.or.us lib.pa.us lib.pr.us lib.ri.us lib.sc.us lib.sd.us lib.tn.us lib.tx.us lib.ut.us lib.vi.us lib.vt.us lib.va.us lib.wa.us lib.wi.us // lib.wv.us Bug 941670 - Removed at request of Larry W Arnold lib.wy.us // k12.ma.us contains school districts in Massachusetts. The 4LDs are // managed independently except for private (PVT), charter (CHTR) and // parochial (PAROCH) schools. Those are delegated directly to the // 5LD operators. pvt.k12.ma.us chtr.k12.ma.us paroch.k12.ma.us // uy : http://www.nic.org.uy/ uy com.uy edu.uy gub.uy mil.uy net.uy org.uy // uz : http://www.reg.uz/ uz co.uz com.uz net.uz org.uz // va : https://en.wikipedia.org/wiki/.va va // vc : https://en.wikipedia.org/wiki/.vc // Submitted by registry vc com.vc net.vc org.vc gov.vc mil.vc edu.vc // ve : https://registro.nic.ve/ // Submitted by registry ve arts.ve co.ve com.ve e12.ve edu.ve firm.ve gob.ve gov.ve info.ve int.ve mil.ve net.ve org.ve rec.ve store.ve tec.ve web.ve // vg : https://en.wikipedia.org/wiki/.vg vg // vi : http://www.nic.vi/newdomainform.htm // http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other // TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they // are available for registration (which they do not seem to be). vi co.vi com.vi k12.vi net.vi org.vi // vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp vn com.vn net.vn org.vn edu.vn gov.vn int.vn ac.vn biz.vn info.vn name.vn pro.vn health.vn // vu : https://en.wikipedia.org/wiki/.vu // http://www.vunic.vu/ vu com.vu edu.vu net.vu org.vu // wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf wf // ws : https://en.wikipedia.org/wiki/.ws // http://samoanic.ws/index.dhtml ws com.ws net.ws org.ws gov.ws edu.ws // yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf yt // IDN ccTLDs // When submitting patches, please maintain a sort by ISO 3166 ccTLD, then // U-label, and follow this format: // // A-Label ("", [, variant info]) : // // [sponsoring org] // U-Label // xn--mgbaam7a8h ("Emerat", Arabic) : AE // http://nic.ae/english/arabicdomain/rules.jsp امارات // xn--y9a3aq ("hye", Armenian) : AM // ISOC AM (operated by .am Registry) հայ // xn--54b7fta0cc ("Bangla", Bangla) : BD বাংলা // xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY // Operated by .by registry бел // xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN // CNNIC // http://cnnic.cn/html/Dir/2005/10/11/3218.htm 中国 // xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN // CNNIC // http://cnnic.cn/html/Dir/2005/10/11/3218.htm 中國 // xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ الجزائر // xn--wgbh1c ("Egypt/Masr", Arabic) : EG // http://www.dotmasr.eg/ مصر // xn--e1a4c ("eu", Cyrillic) : EU ею // xn--node ("ge", Georgian Mkhedruli) : GE გე // xn--qxam ("el", Greek) : GR // Hellenic Ministry of Infrastructure, Transport, and Networks ελ // xn--j6w193g ("Hong Kong", Chinese) : HK // https://www2.hkirc.hk/register/rules.jsp 香港 // xn--h2brj9c ("Bharat", Devanagari) : IN // India भारत // xn--mgbbh1a71e ("Bharat", Arabic) : IN // India بھارت // xn--fpcrj9c3d ("Bharat", Telugu) : IN // India భారత్ // xn--gecrj9c ("Bharat", Gujarati) : IN // India ભારત // xn--s9brj9c ("Bharat", Gurmukhi) : IN // India ਭਾਰਤ // xn--45brj9c ("Bharat", Bengali) : IN // India ভারত // xn--xkc2dl3a5ee0h ("India", Tamil) : IN // India இந்தியா // xn--mgba3a4f16a ("Iran", Persian) : IR ایران // xn--mgba3a4fra ("Iran", Arabic) : IR ايران // xn--mgbtx2b ("Iraq", Arabic) : IQ // Communications and Media Commission عراق // xn--mgbayh7gpa ("al-Ordon", Arabic) : JO // National Information Technology Center (NITC) // Royal Scientific Society, Al-Jubeiha الاردن // xn--3e0b707e ("Republic of Korea", Hangul) : KR 한국 // xn--80ao21a ("Kaz", Kazakh) : KZ қаз // xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK // http://nic.lk ලංකා // xn--xkc2al3hye2a ("Ilangai", Tamil) : LK // http://nic.lk இலங்கை // xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA المغرب // xn--d1alf ("mkd", Macedonian) : MK // MARnet мкд // xn--l1acc ("mon", Mongolian) : MN мон // xn--mix891f ("Macao", Chinese, Traditional) : MO // MONIC / HNET Asia (Registry Operator for .mo) 澳門 // xn--mix082f ("Macao", Chinese, Simplified) : MO 澳门 // xn--mgbx4cd0ab ("Malaysia", Malay) : MY مليسيا // xn--mgb9awbf ("Oman", Arabic) : OM عمان // xn--mgbai9azgqp6j ("Pakistan", Urdu/Arabic) : PK پاکستان // xn--mgbai9a5eva00b ("Pakistan", Urdu/Arabic, variant) : PK پاكستان // xn--ygbi2ammx ("Falasteen", Arabic) : PS // The Palestinian National Internet Naming Authority (PNINA) // http://www.pnina.ps فلسطين // xn--90a3ac ("srb", Cyrillic) : RS // https://www.rnids.rs/en/domains/national-domains срб пр.срб орг.срб обр.срб од.срб упр.срб ак.срб // xn--p1ai ("rf", Russian-Cyrillic) : RU // http://www.cctld.ru/en/docs/rulesrf.php рф // xn--wgbl6a ("Qatar", Arabic) : QA // http://www.ict.gov.qa/ قطر // xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA // http://www.nic.net.sa/ السعودية // xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant) : SA السعودیة // xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA السعودیۃ // xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA السعوديه // xn--mgbpl2fh ("sudan", Arabic) : SD // Operated by .sd registry سودان // xn--yfro4i67o Singapore ("Singapore", Chinese) : SG 新加坡 // xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG சிங்கப்பூர் // xn--ogbpf8fl ("Syria", Arabic) : SY سورية // xn--mgbtf8fl ("Syria", Arabic, variant) : SY سوريا // xn--o3cw4h ("Thai", Thai) : TH // http://www.thnic.co.th ไทย // xn--pgbs0dh ("Tunisia", Arabic) : TN // http://nic.tn تونس // xn--kpry57d ("Taiwan", Chinese, Traditional) : TW // http://www.twnic.net/english/dn/dn_07a.htm 台灣 // xn--kprw13d ("Taiwan", Chinese, Simplified) : TW // http://www.twnic.net/english/dn/dn_07a.htm 台湾 // xn--nnx388a ("Taiwan", Chinese, variant) : TW 臺灣 // xn--j1amh ("ukr", Cyrillic) : UA укр // xn--mgb2ddes ("AlYemen", Arabic) : YE اليمن // xxx : http://icmregistry.com xxx // ye : http://www.y.net.ye/services/domain_name.htm *.ye // za : http://www.zadna.org.za/content/page/domain-information ac.za agric.za alt.za co.za edu.za gov.za grondar.za law.za mil.za net.za ngo.za nis.za nom.za org.za school.za tm.za web.za // zm : https://zicta.zm/ // Submitted by registry zm ac.zm biz.zm co.zm com.zm edu.zm gov.zm info.zm mil.zm net.zm org.zm sch.zm // zw : https://en.wikipedia.org/wiki/.zw *.zw // List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2016-11-29T01:06:51Z // aaa : 2015-02-26 American Automobile Association, Inc. aaa // aarp : 2015-05-21 AARP aarp // abarth : 2015-07-30 Fiat Chrysler Automobiles N.V. abarth // abb : 2014-10-24 ABB Ltd abb // abbott : 2014-07-24 Abbott Laboratories, Inc. abbott // abbvie : 2015-07-30 AbbVie Inc. abbvie // abc : 2015-07-30 Disney Enterprises, Inc. abc // able : 2015-06-25 Able Inc. able // abogado : 2014-04-24 Top Level Domain Holdings Limited abogado // abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre abudhabi // academy : 2013-11-07 Half Oaks, LLC academy // accenture : 2014-08-15 Accenture plc accenture // accountant : 2014-11-20 dot Accountant Limited accountant // accountants : 2014-03-20 Knob Town, LLC accountants // aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG aco // active : 2014-05-01 The Active Network, Inc active // actor : 2013-12-12 United TLD Holdco Ltd. actor // adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC) adac // ads : 2014-12-04 Charleston Road Registry Inc. ads // adult : 2014-10-16 ICM Registry AD LLC adult // aeg : 2015-03-19 Aktiebolaget Electrolux aeg // aetna : 2015-05-21 Aetna Life Insurance Company aetna // afamilycompany : 2015-07-23 Johnson Shareholdings, Inc. afamilycompany // afl : 2014-10-02 Australian Football League afl // africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa africa // agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) agakhan // agency : 2013-11-14 Steel Falls, LLC agency // aig : 2014-12-18 American International Group, Inc. aig // aigo : 2015-08-06 aigo Digital Technology Co,Ltd. aigo // airbus : 2015-07-30 Airbus S.A.S. airbus // airforce : 2014-03-06 United TLD Holdco Ltd. airforce // airtel : 2014-10-24 Bharti Airtel Limited airtel // akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation) akdn // alfaromeo : 2015-07-31 Fiat Chrysler Automobiles N.V. alfaromeo // alibaba : 2015-01-15 Alibaba Group Holding Limited alibaba // alipay : 2015-01-15 Alibaba Group Holding Limited alipay // allfinanz : 2014-07-03 Allfinanz Deutsche Vermögensberatung Aktiengesellschaft allfinanz // allstate : 2015-07-31 Allstate Fire and Casualty Insurance Company allstate // ally : 2015-06-18 Ally Financial Inc. ally // alsace : 2014-07-02 REGION D ALSACE alsace // alstom : 2015-07-30 ALSTOM alstom // americanexpress : 2015-07-31 American Express Travel Related Services Company, Inc. americanexpress // americanfamily : 2015-07-23 AmFam, Inc. americanfamily // amex : 2015-07-31 American Express Travel Related Services Company, Inc. amex // amfam : 2015-07-23 AmFam, Inc. amfam // amica : 2015-05-28 Amica Mutual Insurance Company amica // amsterdam : 2014-07-24 Gemeente Amsterdam amsterdam // analytics : 2014-12-18 Campus IP LLC analytics // android : 2014-08-07 Charleston Road Registry Inc. android // anquan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. anquan // anz : 2015-07-31 Australia and New Zealand Banking Group Limited anz // aol : 2015-09-17 AOL Inc. aol // apartments : 2014-12-11 June Maple, LLC apartments // app : 2015-05-14 Charleston Road Registry Inc. app // apple : 2015-05-14 Apple Inc. apple // aquarelle : 2014-07-24 Aquarelle.com aquarelle // arab : 2015-11-12 League of Arab States arab // aramco : 2014-11-20 Aramco Services Company aramco // archi : 2014-02-06 STARTING DOT LIMITED archi // army : 2014-03-06 United TLD Holdco Ltd. army // art : 2016-03-24 UK Creative Ideas Limited art // arte : 2014-12-11 Association Relative à la Télévision Européenne G.E.I.E. arte // asda : 2015-07-31 Wal-Mart Stores, Inc. asda // associates : 2014-03-06 Baxter Hill, LLC associates // athleta : 2015-07-30 The Gap, Inc. athleta // attorney : 2014-03-20 attorney // auction : 2014-03-20 auction // audi : 2015-05-21 AUDI Aktiengesellschaft audi // audible : 2015-06-25 Amazon EU S.à r.l. audible // audio : 2014-03-20 Uniregistry, Corp. audio // auspost : 2015-08-13 Australian Postal Corporation auspost // author : 2014-12-18 Amazon EU S.à r.l. author // auto : 2014-11-13 auto // autos : 2014-01-09 DERAutos, LLC autos // avianca : 2015-01-08 Aerovias del Continente Americano S.A. Avianca avianca // aws : 2015-06-25 Amazon EU S.à r.l. aws // axa : 2013-12-19 AXA SA axa // azure : 2014-12-18 Microsoft Corporation azure // baby : 2015-04-09 Johnson & Johnson Services, Inc. baby // baidu : 2015-01-08 Baidu, Inc. baidu // banamex : 2015-07-30 Citigroup Inc. banamex // bananarepublic : 2015-07-31 The Gap, Inc. bananarepublic // band : 2014-06-12 band // bank : 2014-09-25 fTLD Registry Services LLC bank // bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable bar // barcelona : 2014-07-24 Municipi de Barcelona barcelona // barclaycard : 2014-11-20 Barclays Bank PLC barclaycard // barclays : 2014-11-20 Barclays Bank PLC barclays // barefoot : 2015-06-11 Gallo Vineyards, Inc. barefoot // bargains : 2013-11-14 Half Hallow, LLC bargains // baseball : 2015-10-29 MLB Advanced Media DH, LLC baseball // basketball : 2015-08-20 Fédération Internationale de Basketball (FIBA) basketball // bauhaus : 2014-04-17 Werkhaus GmbH bauhaus // bayern : 2014-01-23 Bayern Connect GmbH bayern // bbc : 2014-12-18 British Broadcasting Corporation bbc // bbt : 2015-07-23 BB&T Corporation bbt // bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A. bbva // bcg : 2015-04-02 The Boston Consulting Group, Inc. bcg // bcn : 2014-07-24 Municipi de Barcelona bcn // beats : 2015-05-14 Beats Electronics, LLC beats // beauty : 2015-12-03 L'Oréal beauty // beer : 2014-01-09 Top Level Domain Holdings Limited beer // bentley : 2014-12-18 Bentley Motors Limited bentley // berlin : 2013-10-31 dotBERLIN GmbH & Co. KG berlin // best : 2013-12-19 BestTLD Pty Ltd best // bestbuy : 2015-07-31 BBY Solutions, Inc. bestbuy // bet : 2015-05-07 Afilias plc bet // bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited bharti // bible : 2014-06-19 American Bible Society bible // bid : 2013-12-19 dot Bid Limited bid // bike : 2013-08-27 Grand Hollow, LLC bike // bing : 2014-12-18 Microsoft Corporation bing // bingo : 2014-12-04 Sand Cedar, LLC bingo // bio : 2014-03-06 STARTING DOT LIMITED bio // black : 2014-01-16 Afilias Limited black // blackfriday : 2014-01-16 Uniregistry, Corp. blackfriday // blanco : 2015-07-16 BLANCO GmbH + Co KG blanco // blockbuster : 2015-07-30 Dish DBS Corporation blockbuster // blog : 2015-05-14 blog // bloomberg : 2014-07-17 Bloomberg IP Holdings LLC bloomberg // blue : 2013-11-07 Afilias Limited blue // bms : 2014-10-30 Bristol-Myers Squibb Company bms // bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft bmw // bnl : 2014-07-24 Banca Nazionale del Lavoro bnl // bnpparibas : 2014-05-29 BNP Paribas bnpparibas // boats : 2014-12-04 DERBoats, LLC boats // boehringer : 2015-07-09 Boehringer Ingelheim International GmbH boehringer // bofa : 2015-07-31 NMS Services, Inc. bofa // bom : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br bom // bond : 2014-06-05 Bond University Limited bond // boo : 2014-01-30 Charleston Road Registry Inc. boo // book : 2015-08-27 Amazon EU S.à r.l. book // booking : 2015-07-16 Booking.com B.V. booking // boots : 2015-01-08 THE BOOTS COMPANY PLC boots // bosch : 2015-06-18 Robert Bosch GMBH bosch // bostik : 2015-05-28 Bostik SA bostik // boston : 2015-12-10 boston // bot : 2014-12-18 Amazon EU S.à r.l. bot // boutique : 2013-11-14 Over Galley, LLC boutique // box : 2015-11-12 NS1 Limited box // bradesco : 2014-12-18 Banco Bradesco S.A. bradesco // bridgestone : 2014-12-18 Bridgestone Corporation bridgestone // broadway : 2014-12-22 Celebrate Broadway, Inc. broadway // broker : 2014-12-11 IG Group Holdings PLC broker // brother : 2015-01-29 Brother Industries, Ltd. brother // brussels : 2014-02-06 DNS.be vzw brussels // budapest : 2013-11-21 Top Level Domain Holdings Limited budapest // bugatti : 2015-07-23 Bugatti International SA bugatti // build : 2013-11-07 Plan Bee LLC build // builders : 2013-11-07 Atomic Madison, LLC builders // business : 2013-11-07 Spring Cross, LLC business // buy : 2014-12-18 Amazon EU S.à r.l. buy // buzz : 2013-10-02 DOTSTRATEGY CO. buzz // bzh : 2014-02-27 Association www.bzh bzh // cab : 2013-10-24 Half Sunset, LLC cab // cafe : 2015-02-11 Pioneer Canyon, LLC cafe // cal : 2014-07-24 Charleston Road Registry Inc. cal // call : 2014-12-18 Amazon EU S.à r.l. call // calvinklein : 2015-07-30 PVH gTLD Holdings LLC calvinklein // cam : 2016-04-21 AC Webconnecting Holding B.V. cam // camera : 2013-08-27 Atomic Maple, LLC camera // camp : 2013-11-07 Delta Dynamite, LLC camp // cancerresearch : 2014-05-15 Australian Cancer Research Foundation cancerresearch // canon : 2014-09-12 Canon Inc. canon // capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry capetown // capital : 2014-03-06 Delta Mill, LLC capital // capitalone : 2015-08-06 Capital One Financial Corporation capitalone // car : 2015-01-22 car // caravan : 2013-12-12 Caravan International, Inc. caravan // cards : 2013-12-05 Foggy Hollow, LLC cards // care : 2014-03-06 Goose Cross care // career : 2013-10-09 dotCareer LLC career // careers : 2013-10-02 Wild Corner, LLC careers // cars : 2014-11-13 cars // cartier : 2014-06-23 Richemont DNS Inc. cartier // casa : 2013-11-21 Top Level Domain Holdings Limited casa // case : 2015-09-03 CNH Industrial N.V. case // caseih : 2015-09-03 CNH Industrial N.V. caseih // cash : 2014-03-06 Delta Lake, LLC cash // casino : 2014-12-18 Binky Sky, LLC casino // catering : 2013-12-05 New Falls. LLC catering // catholic : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) catholic // cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA cba // cbn : 2014-08-22 The Christian Broadcasting Network, Inc. cbn // cbre : 2015-07-02 CBRE, Inc. cbre // cbs : 2015-08-06 CBS Domains Inc. cbs // ceb : 2015-04-09 The Corporate Executive Board Company ceb // center : 2013-11-07 Tin Mill, LLC center // ceo : 2013-11-07 CEOTLD Pty Ltd ceo // cern : 2014-06-05 European Organization for Nuclear Research ("CERN") cern // cfa : 2014-08-28 CFA Institute cfa // cfd : 2014-12-11 IG Group Holdings PLC cfd // chanel : 2015-04-09 Chanel International B.V. chanel // channel : 2014-05-08 Charleston Road Registry Inc. channel // chase : 2015-04-30 JPMorgan Chase & Co. chase // chat : 2014-12-04 Sand Fields, LLC chat // cheap : 2013-11-14 Sand Cover, LLC cheap // chintai : 2015-06-11 CHINTAI Corporation chintai // chloe : 2014-10-16 Richemont DNS Inc. chloe // christmas : 2013-11-21 Uniregistry, Corp. christmas // chrome : 2014-07-24 Charleston Road Registry Inc. chrome // chrysler : 2015-07-30 FCA US LLC. chrysler // church : 2014-02-06 Holly Fields, LLC church // cipriani : 2015-02-19 Hotel Cipriani Srl cipriani // circle : 2014-12-18 Amazon EU S.à r.l. circle // cisco : 2014-12-22 Cisco Technology, Inc. cisco // citadel : 2015-07-23 Citadel Domain LLC citadel // citi : 2015-07-30 Citigroup Inc. citi // citic : 2014-01-09 CITIC Group Corporation citic // city : 2014-05-29 Snow Sky, LLC city // cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc. cityeats // claims : 2014-03-20 Black Corner, LLC claims // cleaning : 2013-12-05 Fox Shadow, LLC cleaning // click : 2014-06-05 Uniregistry, Corp. click // clinic : 2014-03-20 Goose Park, LLC clinic // clinique : 2015-10-01 The Estée Lauder Companies Inc. clinique // clothing : 2013-08-27 Steel Lake, LLC clothing // cloud : 2015-04-16 ARUBA S.p.A. cloud // club : 2013-11-08 .CLUB DOMAINS, LLC club // clubmed : 2015-06-25 Club Méditerranée S.A. clubmed // coach : 2014-10-09 Koko Island, LLC coach // codes : 2013-10-31 Puff Willow, LLC codes // coffee : 2013-10-17 Trixy Cover, LLC coffee // college : 2014-01-16 XYZ.COM LLC college // cologne : 2014-02-05 NetCologne Gesellschaft für Telekommunikation mbH cologne // comcast : 2015-07-23 Comcast IP Holdings I, LLC comcast // commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA commbank // community : 2013-12-05 Fox Orchard, LLC community // company : 2013-11-07 Silver Avenue, LLC company // compare : 2015-10-08 iSelect Ltd compare // computer : 2013-10-24 Pine Mill, LLC computer // comsec : 2015-01-08 VeriSign, Inc. comsec // condos : 2013-12-05 Pine House, LLC condos // construction : 2013-09-16 Fox Dynamite, LLC construction // consulting : 2013-12-05 consulting // contact : 2015-01-08 Top Level Spectrum, Inc. contact // contractors : 2013-09-10 Magic Woods, LLC contractors // cooking : 2013-11-21 Top Level Domain Holdings Limited cooking // cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. cookingchannel // cool : 2013-11-14 Koko Lake, LLC cool // corsica : 2014-09-25 Collectivité Territoriale de Corse corsica // country : 2013-12-19 Top Level Domain Holdings Limited country // coupon : 2015-02-26 Amazon EU S.à r.l. coupon // coupons : 2015-03-26 Black Island, LLC coupons // courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD courses // credit : 2014-03-20 Snow Shadow, LLC credit // creditcard : 2014-03-20 Binky Frostbite, LLC creditcard // creditunion : 2015-01-22 CUNA Performance Resources, LLC creditunion // cricket : 2014-10-09 dot Cricket Limited cricket // crown : 2014-10-24 Crown Equipment Corporation crown // crs : 2014-04-03 Federated Co-operatives Limited crs // cruise : 2015-12-10 Viking River Cruises (Bermuda) Ltd. cruise // cruises : 2013-12-05 Spring Way, LLC cruises // csc : 2014-09-25 Alliance-One Services, Inc. csc // cuisinella : 2014-04-03 SALM S.A.S. cuisinella // cymru : 2014-05-08 Nominet UK cymru // cyou : 2015-01-22 Beijing Gamease Age Digital Technology Co., Ltd. cyou // dabur : 2014-02-06 Dabur India Limited dabur // dad : 2014-01-23 Charleston Road Registry Inc. dad // dance : 2013-10-24 United TLD Holdco Ltd. dance // data : 2016-06-02 Dish DBS Corporation data // date : 2014-11-20 dot Date Limited date // dating : 2013-12-05 Pine Fest, LLC dating // datsun : 2014-03-27 NISSAN MOTOR CO., LTD. datsun // day : 2014-01-30 Charleston Road Registry Inc. day // dclk : 2014-11-20 Charleston Road Registry Inc. dclk // dds : 2015-05-07 Top Level Domain Holdings Limited dds // deal : 2015-06-25 Amazon EU S.à r.l. deal // dealer : 2014-12-22 Dealer Dot Com, Inc. dealer // deals : 2014-05-22 Sand Sunset, LLC deals // degree : 2014-03-06 degree // delivery : 2014-09-11 Steel Station, LLC delivery // dell : 2014-10-24 Dell Inc. dell // deloitte : 2015-07-31 Deloitte Touche Tohmatsu deloitte // delta : 2015-02-19 Delta Air Lines, Inc. delta // democrat : 2013-10-24 United TLD Holdco Ltd. democrat // dental : 2014-03-20 Tin Birch, LLC dental // dentist : 2014-03-20 dentist // desi : 2013-11-14 Desi Networks LLC desi // design : 2014-11-07 Top Level Design, LLC design // dev : 2014-10-16 Charleston Road Registry Inc. dev // dhl : 2015-07-23 Deutsche Post AG dhl // diamonds : 2013-09-22 John Edge, LLC diamonds // diet : 2014-06-26 Uniregistry, Corp. diet // digital : 2014-03-06 Dash Park, LLC digital // direct : 2014-04-10 Half Trail, LLC direct // directory : 2013-09-20 Extra Madison, LLC directory // discount : 2014-03-06 Holly Hill, LLC discount // discover : 2015-07-23 Discover Financial Services discover // dish : 2015-07-30 Dish DBS Corporation dish // diy : 2015-11-05 Lifestyle Domain Holdings, Inc. diy // dnp : 2013-12-13 Dai Nippon Printing Co., Ltd. dnp // docs : 2014-10-16 Charleston Road Registry Inc. docs // doctor : 2016-06-02 Brice Trail, LLC doctor // dodge : 2015-07-30 FCA US LLC. dodge // dog : 2014-12-04 Koko Mill, LLC dog // doha : 2014-09-18 Communications Regulatory Authority (CRA) doha // domains : 2013-10-17 Sugar Cross, LLC domains // dot : 2015-05-21 Dish DBS Corporation dot // download : 2014-11-20 dot Support Limited download // drive : 2015-03-05 Charleston Road Registry Inc. drive // dtv : 2015-06-04 Dish DBS Corporation dtv // dubai : 2015-01-01 Dubai Smart Government Department dubai // duck : 2015-07-23 Johnson Shareholdings, Inc. duck // dunlop : 2015-07-02 The Goodyear Tire & Rubber Company dunlop // duns : 2015-08-06 The Dun & Bradstreet Corporation duns // dupont : 2015-06-25 E. I. du Pont de Nemours and Company dupont // durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry durban // dvag : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG dvag // dvr : 2016-05-26 Hughes Satellite Systems Corporation dvr // dwg : 2015-07-23 Autodesk, Inc. dwg // earth : 2014-12-04 Interlink Co., Ltd. earth // eat : 2014-01-23 Charleston Road Registry Inc. eat // eco : 2016-07-08 Big Room Inc. eco // edeka : 2014-12-18 EDEKA Verband kaufmännischer Genossenschaften e.V. edeka // education : 2013-11-07 Brice Way, LLC education // email : 2013-10-31 Spring Madison, LLC email // emerck : 2014-04-03 Merck KGaA emerck // energy : 2014-09-11 Binky Birch, LLC energy // engineer : 2014-03-06 United TLD Holdco Ltd. engineer // engineering : 2014-03-06 Romeo Canyon engineering // enterprises : 2013-09-20 Snow Oaks, LLC enterprises // epost : 2015-07-23 Deutsche Post AG epost // epson : 2014-12-04 Seiko Epson Corporation epson // equipment : 2013-08-27 Corn Station, LLC equipment // ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson ericsson // erni : 2014-04-03 ERNI Group Holding AG erni // esq : 2014-05-08 Charleston Road Registry Inc. esq // estate : 2013-08-27 Trixy Park, LLC estate // esurance : 2015-07-23 Esurance Insurance Company esurance // etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) etisalat // eurovision : 2014-04-24 European Broadcasting Union (EBU) eurovision // eus : 2013-12-12 Puntueus Fundazioa eus // events : 2013-12-05 Pioneer Maple, LLC events // everbank : 2014-05-15 EverBank everbank // exchange : 2014-03-06 Spring Falls, LLC exchange // expert : 2013-11-21 Magic Pass, LLC expert // exposed : 2013-12-05 Victor Beach, LLC exposed // express : 2015-02-11 Sea Sunset, LLC express // extraspace : 2015-05-14 Extra Space Storage LLC extraspace // fage : 2014-12-18 Fage International S.A. fage // fail : 2014-03-06 Atomic Pipe, LLC fail // fairwinds : 2014-11-13 FairWinds Partners, LLC fairwinds // faith : 2014-11-20 dot Faith Limited faith // family : 2015-04-02 family // fan : 2014-03-06 fan // fans : 2014-11-07 Asiamix Digital Limited fans // farm : 2013-11-07 Just Maple, LLC farm // farmers : 2015-07-09 Farmers Insurance Exchange farmers // fashion : 2014-07-03 Top Level Domain Holdings Limited fashion // fast : 2014-12-18 Amazon EU S.à r.l. fast // fedex : 2015-08-06 Federal Express Corporation fedex // feedback : 2013-12-19 Top Level Spectrum, Inc. feedback // ferrari : 2015-07-31 Fiat Chrysler Automobiles N.V. ferrari // ferrero : 2014-12-18 Ferrero Trading Lux S.A. ferrero // fiat : 2015-07-31 Fiat Chrysler Automobiles N.V. fiat // fidelity : 2015-07-30 Fidelity Brokerage Services LLC fidelity // fido : 2015-08-06 Rogers Communications Partnership fido // film : 2015-01-08 Motion Picture Domain Registry Pty Ltd film // final : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br final // finance : 2014-03-20 Cotton Cypress, LLC finance // financial : 2014-03-06 Just Cover, LLC financial // fire : 2015-06-25 Amazon EU S.à r.l. fire // firestone : 2014-12-18 Bridgestone Corporation firestone // firmdale : 2014-03-27 Firmdale Holdings Limited firmdale // fish : 2013-12-12 Fox Woods, LLC fish // fishing : 2013-11-21 Top Level Domain Holdings Limited fishing // fit : 2014-11-07 Top Level Domain Holdings Limited fit // fitness : 2014-03-06 Brice Orchard, LLC fitness // flickr : 2015-04-02 Yahoo! Domain Services Inc. flickr // flights : 2013-12-05 Fox Station, LLC flights // flir : 2015-07-23 FLIR Systems, Inc. flir // florist : 2013-11-07 Half Cypress, LLC florist // flowers : 2014-10-09 Uniregistry, Corp. flowers // fly : 2014-05-08 Charleston Road Registry Inc. fly // foo : 2014-01-23 Charleston Road Registry Inc. foo // food : 2016-04-21 Lifestyle Domain Holdings, Inc. food // foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc. foodnetwork // football : 2014-12-18 Foggy Farms, LLC football // ford : 2014-11-13 Ford Motor Company ford // forex : 2014-12-11 IG Group Holdings PLC forex // forsale : 2014-05-22 forsale // forum : 2015-04-02 Fegistry, LLC forum // foundation : 2013-12-05 John Dale, LLC foundation // fox : 2015-09-11 FOX Registry, LLC fox // free : 2015-12-10 Amazon EU S.à r.l. free // fresenius : 2015-07-30 Fresenius Immobilien-Verwaltungs-GmbH fresenius // frl : 2014-05-15 FRLregistry B.V. frl // frogans : 2013-12-19 OP3FT frogans // frontdoor : 2015-07-02 Lifestyle Domain Holdings, Inc. frontdoor // frontier : 2015-02-05 Frontier Communications Corporation frontier // ftr : 2015-07-16 Frontier Communications Corporation ftr // fujitsu : 2015-07-30 Fujitsu Limited fujitsu // fujixerox : 2015-07-23 Xerox DNHC LLC fujixerox // fun : 2016-01-14 fun // fund : 2014-03-20 John Castle, LLC fund // furniture : 2014-03-20 Lone Fields, LLC furniture // futbol : 2013-09-20 futbol // fyi : 2015-04-02 Silver Tigers, LLC fyi // gal : 2013-11-07 Asociación puntoGAL gal // gallery : 2013-09-13 Sugar House, LLC gallery // gallo : 2015-06-11 Gallo Vineyards, Inc. gallo // gallup : 2015-02-19 Gallup, Inc. gallup // game : 2015-05-28 Uniregistry, Corp. game // games : 2015-05-28 games // gap : 2015-07-31 The Gap, Inc. gap // garden : 2014-06-26 Top Level Domain Holdings Limited garden // gbiz : 2014-07-17 Charleston Road Registry Inc. gbiz // gdn : 2014-07-31 Joint Stock Company "Navigation-information systems" gdn // gea : 2014-12-04 GEA Group Aktiengesellschaft gea // gent : 2014-01-23 COMBELL GROUP NV/SA gent // genting : 2015-03-12 Resorts World Inc Pte. Ltd. genting // george : 2015-07-31 Wal-Mart Stores, Inc. george // ggee : 2014-01-09 GMO Internet, Inc. ggee // gift : 2013-10-17 Uniregistry, Corp. gift // gifts : 2014-07-03 Goose Sky, LLC gifts // gives : 2014-03-06 United TLD Holdco Ltd. gives // giving : 2014-11-13 Giving Limited giving // glade : 2015-07-23 Johnson Shareholdings, Inc. glade // glass : 2013-11-07 Black Cover, LLC glass // gle : 2014-07-24 Charleston Road Registry Inc. gle // global : 2014-04-17 Dot GLOBAL AS global // globo : 2013-12-19 Globo Comunicação e Participações S.A globo // gmail : 2014-05-01 Charleston Road Registry Inc. gmail // gmbh : 2016-01-29 Extra Dynamite, LLC gmbh // gmo : 2014-01-09 GMO Internet, Inc. gmo // gmx : 2014-04-24 1&1 Mail & Media GmbH gmx // godaddy : 2015-07-23 Go Daddy East, LLC godaddy // gold : 2015-01-22 June Edge, LLC gold // goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD. goldpoint // golf : 2014-12-18 Lone falls, LLC golf // goo : 2014-12-18 NTT Resonant Inc. goo // goodhands : 2015-07-31 Allstate Fire and Casualty Insurance Company goodhands // goodyear : 2015-07-02 The Goodyear Tire & Rubber Company goodyear // goog : 2014-11-20 Charleston Road Registry Inc. goog // google : 2014-07-24 Charleston Road Registry Inc. google // gop : 2014-01-16 Republican State Leadership Committee, Inc. gop // got : 2014-12-18 Amazon EU S.à r.l. got // grainger : 2015-05-07 Grainger Registry Services, LLC grainger // graphics : 2013-09-13 Over Madison, LLC graphics // gratis : 2014-03-20 Pioneer Tigers, LLC gratis // green : 2014-05-08 Afilias Limited green // gripe : 2014-03-06 Corn Sunset, LLC gripe // grocery : 2016-06-16 Wal-Mart Stores, Inc. grocery // group : 2014-08-15 Romeo Town, LLC group // guardian : 2015-07-30 The Guardian Life Insurance Company of America guardian // gucci : 2014-11-13 Guccio Gucci S.p.a. gucci // guge : 2014-08-28 Charleston Road Registry Inc. guge // guide : 2013-09-13 Snow Moon, LLC guide // guitars : 2013-11-14 Uniregistry, Corp. guitars // guru : 2013-08-27 Pioneer Cypress, LLC guru // hair : 2015-12-03 L'Oréal hair // hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH hamburg // hangout : 2014-11-13 Charleston Road Registry Inc. hangout // haus : 2013-12-05 haus // hbo : 2015-07-30 HBO Registry Services, Inc. hbo // hdfc : 2015-07-30 HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED hdfc // hdfcbank : 2015-02-12 HDFC Bank Limited hdfcbank // health : 2015-02-11 DotHealth, LLC health // healthcare : 2014-06-12 Silver Glen, LLC healthcare // help : 2014-06-26 Uniregistry, Corp. help // helsinki : 2015-02-05 City of Helsinki helsinki // here : 2014-02-06 Charleston Road Registry Inc. here // hermes : 2014-07-10 HERMES INTERNATIONAL hermes // hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc. hgtv // hiphop : 2014-03-06 Uniregistry, Corp. hiphop // hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc. hisamitsu // hitachi : 2014-10-31 Hitachi, Ltd. hitachi // hiv : 2014-03-13 hiv // hkt : 2015-05-14 PCCW-HKT DataCom Services Limited hkt // hockey : 2015-03-19 Half Willow, LLC hockey // holdings : 2013-08-27 John Madison, LLC holdings // holiday : 2013-11-07 Goose Woods, LLC holiday // homedepot : 2015-04-02 Homer TLC, Inc. homedepot // homegoods : 2015-07-16 The TJX Companies, Inc. homegoods // homes : 2014-01-09 DERHomes, LLC homes // homesense : 2015-07-16 The TJX Companies, Inc. homesense // honda : 2014-12-18 Honda Motor Co., Ltd. honda // honeywell : 2015-07-23 Honeywell GTLD LLC honeywell // horse : 2013-11-21 Top Level Domain Holdings Limited horse // hospital : 2016-10-20 Ruby Pike, LLC hospital // host : 2014-04-17 DotHost Inc. host // hosting : 2014-05-29 Uniregistry, Corp. hosting // hot : 2015-08-27 Amazon EU S.à r.l. hot // hoteles : 2015-03-05 Travel Reservations SRL hoteles // hotels : 2016-04-07 Booking.com B.V. hotels // hotmail : 2014-12-18 Microsoft Corporation hotmail // house : 2013-11-07 Sugar Park, LLC house // how : 2014-01-23 Charleston Road Registry Inc. how // hsbc : 2014-10-24 HSBC Holdings PLC hsbc // htc : 2015-04-02 HTC corporation htc // hughes : 2015-07-30 Hughes Satellite Systems Corporation hughes // hyatt : 2015-07-30 Hyatt GTLD, L.L.C. hyatt // hyundai : 2015-07-09 Hyundai Motor Company hyundai // ibm : 2014-07-31 International Business Machines Corporation ibm // icbc : 2015-02-19 Industrial and Commercial Bank of China Limited icbc // ice : 2014-10-30 IntercontinentalExchange, Inc. ice // icu : 2015-01-08 One.com A/S icu // ieee : 2015-07-23 IEEE Global LLC ieee // ifm : 2014-01-30 ifm electronic gmbh ifm // iinet : 2014-07-03 Connect West Pty. Ltd. iinet // ikano : 2015-07-09 Ikano S.A. ikano // imamat : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) imamat // imdb : 2015-06-25 Amazon EU S.à r.l. imdb // immo : 2014-07-10 Auburn Bloom, LLC immo // immobilien : 2013-11-07 United TLD Holdco Ltd. immobilien // industries : 2013-12-05 Outer House, LLC industries // infiniti : 2014-03-27 NISSAN MOTOR CO., LTD. infiniti // ing : 2014-01-23 Charleston Road Registry Inc. ing // ink : 2013-12-05 Top Level Design, LLC ink // institute : 2013-11-07 Outer Maple, LLC institute // insurance : 2015-02-19 fTLD Registry Services LLC insurance // insure : 2014-03-20 Pioneer Willow, LLC insure // intel : 2015-08-06 Intel Corporation intel // international : 2013-11-07 Wild Way, LLC international // intuit : 2015-07-30 Intuit Administrative Services, Inc. intuit // investments : 2014-03-20 Holly Glen, LLC investments // ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A. ipiranga // irish : 2014-08-07 Dot-Irish LLC irish // iselect : 2015-02-11 iSelect Ltd iselect // ismaili : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation) ismaili // ist : 2014-08-28 Istanbul Metropolitan Municipality ist // istanbul : 2014-08-28 Istanbul Metropolitan Municipality istanbul // itau : 2014-10-02 Itau Unibanco Holding S.A. itau // itv : 2015-07-09 ITV Services Limited itv // iveco : 2015-09-03 CNH Industrial N.V. iveco // iwc : 2014-06-23 Richemont DNS Inc. iwc // jaguar : 2014-11-13 Jaguar Land Rover Ltd jaguar // java : 2014-06-19 Oracle Corporation java // jcb : 2014-11-20 JCB Co., Ltd. jcb // jcp : 2015-04-23 JCP Media, Inc. jcp // jeep : 2015-07-30 FCA US LLC. jeep // jetzt : 2014-01-09 jetzt // jewelry : 2015-03-05 Wild Bloom, LLC jewelry // jio : 2015-04-02 Affinity Names, Inc. jio // jlc : 2014-12-04 Richemont DNS Inc. jlc // jll : 2015-04-02 Jones Lang LaSalle Incorporated jll // jmp : 2015-03-26 Matrix IP LLC jmp // jnj : 2015-06-18 Johnson & Johnson Services, Inc. jnj // joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry joburg // jot : 2014-12-18 Amazon EU S.à r.l. jot // joy : 2014-12-18 Amazon EU S.à r.l. joy // jpmorgan : 2015-04-30 JPMorgan Chase & Co. jpmorgan // jprs : 2014-09-18 Japan Registry Services Co., Ltd. jprs // juegos : 2014-03-20 Uniregistry, Corp. juegos // juniper : 2015-07-30 JUNIPER NETWORKS, INC. juniper // kaufen : 2013-11-07 United TLD Holdco Ltd. kaufen // kddi : 2014-09-12 KDDI CORPORATION kddi // kerryhotels : 2015-04-30 Kerry Trading Co. Limited kerryhotels // kerrylogistics : 2015-04-09 Kerry Trading Co. Limited kerrylogistics // kerryproperties : 2015-04-09 Kerry Trading Co. Limited kerryproperties // kfh : 2014-12-04 Kuwait Finance House kfh // kia : 2015-07-09 KIA MOTORS CORPORATION kia // kim : 2013-09-23 Afilias Limited kim // kinder : 2014-11-07 Ferrero Trading Lux S.A. kinder // kindle : 2015-06-25 Amazon EU S.à r.l. kindle // kitchen : 2013-09-20 Just Goodbye, LLC kitchen // kiwi : 2013-09-20 DOT KIWI LIMITED kiwi // koeln : 2014-01-09 NetCologne Gesellschaft für Telekommunikation mbH koeln // komatsu : 2015-01-08 Komatsu Ltd. komatsu // kosher : 2015-08-20 Kosher Marketing Assets LLC kosher // kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft) kpmg // kpn : 2015-01-08 Koninklijke KPN N.V. kpn // krd : 2013-12-05 KRG Department of Information Technology krd // kred : 2013-12-19 KredTLD Pty Ltd kred // kuokgroup : 2015-04-09 Kerry Trading Co. Limited kuokgroup // kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen kyoto // lacaixa : 2014-01-09 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA lacaixa // ladbrokes : 2015-08-06 LADBROKES INTERNATIONAL PLC ladbrokes // lamborghini : 2015-06-04 Automobili Lamborghini S.p.A. lamborghini // lamer : 2015-10-01 The Estée Lauder Companies Inc. lamer // lancaster : 2015-02-12 LANCASTER lancaster // lancia : 2015-07-31 Fiat Chrysler Automobiles N.V. lancia // lancome : 2015-07-23 L'Oréal lancome // land : 2013-09-10 Pine Moon, LLC land // landrover : 2014-11-13 Jaguar Land Rover Ltd landrover // lanxess : 2015-07-30 LANXESS Corporation lanxess // lasalle : 2015-04-02 Jones Lang LaSalle Incorporated lasalle // lat : 2014-10-16 ECOM-LAC Federaciòn de Latinoamèrica y el Caribe para Internet y el Comercio Electrònico lat // latino : 2015-07-30 Dish DBS Corporation latino // latrobe : 2014-06-16 La Trobe University latrobe // law : 2015-01-22 Minds + Machines Group Limited law // lawyer : 2014-03-20 lawyer // lds : 2014-03-20 IRI Domain Management, LLC ("Applicant") lds // lease : 2014-03-06 Victor Trail, LLC lease // leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc leclerc // lefrak : 2015-07-16 LeFrak Organization, Inc. lefrak // legal : 2014-10-16 Blue Falls, LLC legal // lego : 2015-07-16 LEGO Juris A/S lego // lexus : 2015-04-23 TOYOTA MOTOR CORPORATION lexus // lgbt : 2014-05-08 Afilias Limited lgbt // liaison : 2014-10-02 Liaison Technologies, Incorporated liaison // lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG lidl // life : 2014-02-06 Trixy Oaks, LLC life // lifeinsurance : 2015-01-15 American Council of Life Insurers lifeinsurance // lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc. lifestyle // lighting : 2013-08-27 John McCook, LLC lighting // like : 2014-12-18 Amazon EU S.à r.l. like // lilly : 2015-07-31 Eli Lilly and Company lilly // limited : 2014-03-06 Big Fest, LLC limited // limo : 2013-10-17 Hidden Frostbite, LLC limo // lincoln : 2014-11-13 Ford Motor Company lincoln // linde : 2014-12-04 Linde Aktiengesellschaft linde // link : 2013-11-14 Uniregistry, Corp. link // lipsy : 2015-06-25 Lipsy Ltd lipsy // live : 2014-12-04 live // living : 2015-07-30 Lifestyle Domain Holdings, Inc. living // lixil : 2015-03-19 LIXIL Group Corporation lixil // loan : 2014-11-20 dot Loan Limited loan // loans : 2014-03-20 June Woods, LLC loans // locker : 2015-06-04 Dish DBS Corporation locker // locus : 2015-06-25 Locus Analytics LLC locus // loft : 2015-07-30 Annco, Inc. loft // lol : 2015-01-30 Uniregistry, Corp. lol // london : 2013-11-14 Dot London Domains Limited london // lotte : 2014-11-07 Lotte Holdings Co., Ltd. lotte // lotto : 2014-04-10 Afilias Limited lotto // love : 2014-12-22 Merchant Law Group LLP love // lpl : 2015-07-30 LPL Holdings, Inc. lpl // lplfinancial : 2015-07-30 LPL Holdings, Inc. lplfinancial // ltd : 2014-09-25 Over Corner, LLC ltd // ltda : 2014-04-17 DOMAIN ROBOT SERVICOS DE HOSPEDAGEM NA INTERNET LTDA ltda // lundbeck : 2015-08-06 H. Lundbeck A/S lundbeck // lupin : 2014-11-07 LUPIN LIMITED lupin // luxe : 2014-01-09 Top Level Domain Holdings Limited luxe // luxury : 2013-10-17 Luxury Partners, LLC luxury // macys : 2015-07-31 Macys, Inc. macys // madrid : 2014-05-01 Comunidad de Madrid madrid // maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF) maif // maison : 2013-12-05 Victor Frostbite, LLC maison // makeup : 2015-01-15 L'Oréal makeup // man : 2014-12-04 MAN SE man // management : 2013-11-07 John Goodbye, LLC management // mango : 2013-10-24 PUNTO FA S.L. mango // map : 2016-06-09 Charleston Road Registry Inc. map // market : 2014-03-06 market // marketing : 2013-11-07 Fern Pass, LLC marketing // markets : 2014-12-11 IG Group Holdings PLC markets // marriott : 2014-10-09 Marriott Worldwide Corporation marriott // marshalls : 2015-07-16 The TJX Companies, Inc. marshalls // maserati : 2015-07-31 Fiat Chrysler Automobiles N.V. maserati // mattel : 2015-08-06 Mattel Sites, Inc. mattel // mba : 2015-04-02 Lone Hollow, LLC mba // mcd : 2015-07-30 McDonald’s Corporation mcd // mcdonalds : 2015-07-30 McDonald’s Corporation mcdonalds // mckinsey : 2015-07-31 McKinsey Holdings, Inc. mckinsey // med : 2015-08-06 Medistry LLC med // media : 2014-03-06 Grand Glen, LLC media // meet : 2014-01-16 meet // melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation melbourne // meme : 2014-01-30 Charleston Road Registry Inc. meme // memorial : 2014-10-16 Dog Beach, LLC memorial // men : 2015-02-26 Exclusive Registry Limited men // menu : 2013-09-11 Wedding TLD2, LLC menu // meo : 2014-11-07 PT Comunicacoes S.A. meo // merckmsd : 2016-07-14 MSD Registry Holdings, Inc. merckmsd // metlife : 2015-05-07 MetLife Services and Solutions, LLC metlife // miami : 2013-12-19 Top Level Domain Holdings Limited miami // microsoft : 2014-12-18 Microsoft Corporation microsoft // mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft mini // mint : 2015-07-30 Intuit Administrative Services, Inc. mint // mit : 2015-07-02 Massachusetts Institute of Technology mit // mitsubishi : 2015-07-23 Mitsubishi Corporation mitsubishi // mlb : 2015-05-21 MLB Advanced Media DH, LLC mlb // mls : 2015-04-23 The Canadian Real Estate Association mls // mma : 2014-11-07 MMA IARD mma // mobile : 2016-06-02 Dish DBS Corporation mobile // mobily : 2014-12-18 GreenTech Consultancy Company W.L.L. mobily // moda : 2013-11-07 United TLD Holdco Ltd. moda // moe : 2013-11-13 Interlink Co., Ltd. moe // moi : 2014-12-18 Amazon EU S.à r.l. moi // mom : 2015-04-16 Uniregistry, Corp. mom // monash : 2013-09-30 Monash University monash // money : 2014-10-16 Outer McCook, LLC money // monster : 2015-09-11 Monster Worldwide, Inc. monster // montblanc : 2014-06-23 Richemont DNS Inc. montblanc // mopar : 2015-07-30 FCA US LLC. mopar // mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant") mormon // mortgage : 2014-03-20 mortgage // moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) moscow // moto : 2015-06-04 moto // motorcycles : 2014-01-09 DERMotorcycles, LLC motorcycles // mov : 2014-01-30 Charleston Road Registry Inc. mov // movie : 2015-02-05 New Frostbite, LLC movie // movistar : 2014-10-16 Telefónica S.A. movistar // msd : 2015-07-23 MSD Registry Holdings, Inc. msd // mtn : 2014-12-04 MTN Dubai Limited mtn // mtpc : 2014-11-20 Mitsubishi Tanabe Pharma Corporation mtpc // mtr : 2015-03-12 MTR Corporation Limited mtr // mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC mutual // mutuelle : 2015-06-18 Fédération Nationale de la Mutualité Française mutuelle // nab : 2015-08-20 National Australia Bank Limited nab // nadex : 2014-12-11 IG Group Holdings PLC nadex // nagoya : 2013-10-24 GMO Registry, Inc. nagoya // nationwide : 2015-07-23 Nationwide Mutual Insurance Company nationwide // natura : 2015-03-12 NATURA COSMÉTICOS S.A. natura // navy : 2014-03-06 United TLD Holdco Ltd. navy // nba : 2015-07-31 NBA REGISTRY, LLC nba // nec : 2015-01-08 NEC Corporation nec // netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA netbank // netflix : 2015-06-18 Netflix, Inc. netflix // network : 2013-11-14 Trixy Manor, LLC network // neustar : 2013-12-05 NeuStar, Inc. neustar // new : 2014-01-30 Charleston Road Registry Inc. new // newholland : 2015-09-03 CNH Industrial N.V. newholland // news : 2014-12-18 news // next : 2015-06-18 Next plc next // nextdirect : 2015-06-18 Next plc nextdirect // nexus : 2014-07-24 Charleston Road Registry Inc. nexus // nfl : 2015-07-23 NFL Reg Ops LLC nfl // ngo : 2014-03-06 Public Interest Registry ngo // nhk : 2014-02-13 Japan Broadcasting Corporation (NHK) nhk // nico : 2014-12-04 DWANGO Co., Ltd. nico // nike : 2015-07-23 NIKE, Inc. nike // nikon : 2015-05-21 NIKON CORPORATION nikon // ninja : 2013-11-07 United TLD Holdco Ltd. ninja // nissan : 2014-03-27 NISSAN MOTOR CO., LTD. nissan // nissay : 2015-10-29 Nippon Life Insurance Company nissay // nokia : 2015-01-08 Nokia Corporation nokia // northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC northwesternmutual // norton : 2014-12-04 Symantec Corporation norton // now : 2015-06-25 Amazon EU S.à r.l. now // nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. nowruz // nowtv : 2015-05-14 Starbucks (HK) Limited nowtv // nra : 2014-05-22 NRA Holdings Company, INC. nra // nrw : 2013-11-21 Minds + Machines GmbH nrw // ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION ntt // nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications nyc // obi : 2014-09-25 OBI Group Holding SE & Co. KGaA obi // observer : 2015-04-30 observer // off : 2015-07-23 Johnson Shareholdings, Inc. off // office : 2015-03-12 Microsoft Corporation office // okinawa : 2013-12-05 BusinessRalliart Inc. okinawa // olayan : 2015-05-14 Crescent Holding GmbH olayan // olayangroup : 2015-05-14 Crescent Holding GmbH olayangroup // oldnavy : 2015-07-31 The Gap, Inc. oldnavy // ollo : 2015-06-04 Dish DBS Corporation ollo // omega : 2015-01-08 The Swatch Group Ltd omega // one : 2014-11-07 One.com A/S one // ong : 2014-03-06 Public Interest Registry ong // onl : 2013-09-16 I-Registry Ltd. onl // online : 2015-01-15 DotOnline Inc. online // onyourside : 2015-07-23 Nationwide Mutual Insurance Company onyourside // ooo : 2014-01-09 INFIBEAM INCORPORATION LIMITED ooo // open : 2015-07-31 American Express Travel Related Services Company, Inc. open // oracle : 2014-06-19 Oracle Corporation oracle // orange : 2015-03-12 Orange Brand Services Limited orange // organic : 2014-03-27 Afilias Limited organic // orientexpress : 2015-02-05 orientexpress // origins : 2015-10-01 The Estée Lauder Companies Inc. origins // osaka : 2014-09-04 Interlink Co., Ltd. osaka // otsuka : 2013-10-11 Otsuka Holdings Co., Ltd. otsuka // ott : 2015-06-04 Dish DBS Corporation ott // ovh : 2014-01-16 OVH SAS ovh // page : 2014-12-04 Charleston Road Registry Inc. page // pamperedchef : 2015-02-05 The Pampered Chef, Ltd. pamperedchef // panasonic : 2015-07-30 Panasonic Corporation panasonic // panerai : 2014-11-07 Richemont DNS Inc. panerai // paris : 2014-01-30 City of Paris paris // pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. pars // partners : 2013-12-05 Magic Glen, LLC partners // parts : 2013-12-05 Sea Goodbye, LLC parts // party : 2014-09-11 Blue Sky Registry Limited party // passagens : 2015-03-05 Travel Reservations SRL passagens // pay : 2015-08-27 Amazon EU S.à r.l. pay // pccw : 2015-05-14 PCCW Enterprises Limited pccw // pet : 2015-05-07 Afilias plc pet // pfizer : 2015-09-11 Pfizer Inc. pfizer // pharmacy : 2014-06-19 National Association of Boards of Pharmacy pharmacy // phd : 2016-07-28 Charleston Road Registry Inc. phd // philips : 2014-11-07 Koninklijke Philips N.V. philips // phone : 2016-06-02 Dish DBS Corporation phone // photo : 2013-11-14 Uniregistry, Corp. photo // photography : 2013-09-20 Sugar Glen, LLC photography // photos : 2013-10-17 Sea Corner, LLC photos // physio : 2014-05-01 PhysBiz Pty Ltd physio // piaget : 2014-10-16 Richemont DNS Inc. piaget // pics : 2013-11-14 Uniregistry, Corp. pics // pictet : 2014-06-26 Pictet Europe S.A. pictet // pictures : 2014-03-06 Foggy Sky, LLC pictures // pid : 2015-01-08 Top Level Spectrum, Inc. pid // pin : 2014-12-18 Amazon EU S.à r.l. pin // ping : 2015-06-11 Ping Registry Provider, Inc. ping // pink : 2013-10-01 Afilias Limited pink // pioneer : 2015-07-16 Pioneer Corporation pioneer // pizza : 2014-06-26 Foggy Moon, LLC pizza // place : 2014-04-24 Snow Galley, LLC place // play : 2015-03-05 Charleston Road Registry Inc. play // playstation : 2015-07-02 Sony Computer Entertainment Inc. playstation // plumbing : 2013-09-10 Spring Tigers, LLC plumbing // plus : 2015-02-05 Sugar Mill, LLC plus // pnc : 2015-07-02 PNC Domain Co., LLC pnc // pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG pohl // poker : 2014-07-03 Afilias Domains No. 5 Limited poker // politie : 2015-08-20 Politie Nederland politie // porn : 2014-10-16 ICM Registry PN LLC porn // pramerica : 2015-07-30 Prudential Financial, Inc. pramerica // praxi : 2013-12-05 Praxi S.p.A. praxi // press : 2014-04-03 DotPress Inc. press // prime : 2015-06-25 Amazon EU S.à r.l. prime // prod : 2014-01-23 Charleston Road Registry Inc. prod // productions : 2013-12-05 Magic Birch, LLC productions // prof : 2014-07-24 Charleston Road Registry Inc. prof // progressive : 2015-07-23 Progressive Casualty Insurance Company progressive // promo : 2014-12-18 promo // properties : 2013-12-05 Big Pass, LLC properties // property : 2014-05-22 Uniregistry, Corp. property // protection : 2015-04-23 protection // pru : 2015-07-30 Prudential Financial, Inc. pru // prudential : 2015-07-30 Prudential Financial, Inc. prudential // pub : 2013-12-12 United TLD Holdco Ltd. pub // pwc : 2015-10-29 PricewaterhouseCoopers LLP pwc // qpon : 2013-11-14 dotCOOL, Inc. qpon // quebec : 2013-12-19 PointQuébec Inc quebec // quest : 2015-03-26 Quest ION Limited quest // qvc : 2015-07-30 QVC, Inc. qvc // racing : 2014-12-04 Premier Registry Limited racing // radio : 2016-07-21 European Broadcasting Union (EBU) radio // raid : 2015-07-23 Johnson Shareholdings, Inc. raid // read : 2014-12-18 Amazon EU S.à r.l. read // realestate : 2015-09-11 dotRealEstate LLC realestate // realtor : 2014-05-29 Real Estate Domains LLC realtor // realty : 2015-03-19 Fegistry, LLC realty // recipes : 2013-10-17 Grand Island, LLC recipes // red : 2013-11-07 Afilias Limited red // redstone : 2014-10-31 Redstone Haute Couture Co., Ltd. redstone // redumbrella : 2015-03-26 Travelers TLD, LLC redumbrella // rehab : 2014-03-06 United TLD Holdco Ltd. rehab // reise : 2014-03-13 reise // reisen : 2014-03-06 New Cypress, LLC reisen // reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc. reit // reliance : 2015-04-02 Reliance Industries Limited reliance // ren : 2013-12-12 Beijing Qianxiang Wangjing Technology Development Co., Ltd. ren // rent : 2014-12-04 DERRent, LLC rent // rentals : 2013-12-05 Big Hollow,LLC rentals // repair : 2013-11-07 Lone Sunset, LLC repair // report : 2013-12-05 Binky Glen, LLC report // republican : 2014-03-20 United TLD Holdco Ltd. republican // rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable rest // restaurant : 2014-07-03 Snow Avenue, LLC restaurant // review : 2014-11-20 dot Review Limited review // reviews : 2013-09-13 reviews // rexroth : 2015-06-18 Robert Bosch GMBH rexroth // rich : 2013-11-21 I-Registry Ltd. rich // richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited richardli // ricoh : 2014-11-20 Ricoh Company, Ltd. ricoh // rightathome : 2015-07-23 Johnson Shareholdings, Inc. rightathome // ril : 2015-04-02 Reliance Industries Limited ril // rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO rio // rip : 2014-07-10 United TLD Holdco Ltd. rip // rmit : 2015-11-19 Royal Melbourne Institute of Technology rmit // rocher : 2014-12-18 Ferrero Trading Lux S.A. rocher // rocks : 2013-11-14 rocks // rodeo : 2013-12-19 Top Level Domain Holdings Limited rodeo // rogers : 2015-08-06 Rogers Communications Partnership rogers // room : 2014-12-18 Amazon EU S.à r.l. room // rsvp : 2014-05-08 Charleston Road Registry Inc. rsvp // ruhr : 2013-10-02 regiodot GmbH & Co. KG ruhr // run : 2015-03-19 Snow Park, LLC run // rwe : 2015-04-02 RWE AG rwe // ryukyu : 2014-01-09 BusinessRalliart Inc. ryukyu // saarland : 2013-12-12 dotSaarland GmbH saarland // safe : 2014-12-18 Amazon EU S.à r.l. safe // safety : 2015-01-08 Safety Registry Services, LLC. safety // sakura : 2014-12-18 SAKURA Internet Inc. sakura // sale : 2014-10-16 sale // salon : 2014-12-11 Outer Orchard, LLC salon // samsclub : 2015-07-31 Wal-Mart Stores, Inc. samsclub // samsung : 2014-04-03 SAMSUNG SDS CO., LTD samsung // sandvik : 2014-11-13 Sandvik AB sandvik // sandvikcoromant : 2014-11-07 Sandvik AB sandvikcoromant // sanofi : 2014-10-09 Sanofi sanofi // sap : 2014-03-27 SAP AG sap // sapo : 2014-11-07 PT Comunicacoes S.A. sapo // sarl : 2014-07-03 Delta Orchard, LLC sarl // sas : 2015-04-02 Research IP LLC sas // save : 2015-06-25 Amazon EU S.à r.l. save // saxo : 2014-10-31 Saxo Bank A/S saxo // sbi : 2015-03-12 STATE BANK OF INDIA sbi // sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION sbs // sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) sca // scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB") scb // schaeffler : 2015-08-06 Schaeffler Technologies AG & Co. KG schaeffler // schmidt : 2014-04-03 SALM S.A.S. schmidt // scholarships : 2014-04-24 Scholarships.com, LLC scholarships // school : 2014-12-18 Little Galley, LLC school // schule : 2014-03-06 Outer Moon, LLC schule // schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG schwarz // science : 2014-09-11 dot Science Limited science // scjohnson : 2015-07-23 Johnson Shareholdings, Inc. scjohnson // scor : 2014-10-31 SCOR SE scor // scot : 2014-01-23 Dot Scot Registry Limited scot // search : 2016-06-09 Charleston Road Registry Inc. search // seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal) seat // secure : 2015-08-27 Amazon EU S.à r.l. secure // security : 2015-05-14 security // seek : 2014-12-04 Seek Limited seek // select : 2015-10-08 iSelect Ltd select // sener : 2014-10-24 Sener Ingeniería y Sistemas, S.A. sener // services : 2014-02-27 Fox Castle, LLC services // ses : 2015-07-23 SES ses // seven : 2015-08-06 Seven West Media Ltd seven // sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG sew // sex : 2014-11-13 ICM Registry SX LLC sex // sexy : 2013-09-11 Uniregistry, Corp. sexy // sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR sfr // shangrila : 2015-09-03 Shangri‐La International Hotel Management Limited shangrila // sharp : 2014-05-01 Sharp Corporation sharp // shaw : 2015-04-23 Shaw Cablesystems G.P. shaw // shell : 2015-07-30 Shell Information Technology International Inc shell // shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. shia // shiksha : 2013-11-14 Afilias Limited shiksha // shoes : 2013-10-02 Binky Galley, LLC shoes // shop : 2016-04-08 GMO Registry, Inc. shop // shopping : 2016-03-31 shopping // shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. shouji // show : 2015-03-05 Snow Beach, LLC show // showtime : 2015-08-06 CBS Domains Inc. showtime // shriram : 2014-01-23 Shriram Capital Ltd. shriram // silk : 2015-06-25 Amazon EU S.à r.l. silk // sina : 2015-03-12 Sina Corporation sina // singles : 2013-08-27 Fern Madison, LLC singles // site : 2015-01-15 DotSite Inc. site // ski : 2015-04-09 STARTING DOT LIMITED ski // skin : 2015-01-15 L'Oréal skin // sky : 2014-06-19 Sky IP International Ltd, a company incorporated in England and Wales, operating via its registered Swiss branch sky // skype : 2014-12-18 Microsoft Corporation skype // sling : 2015-07-30 Hughes Satellite Systems Corporation sling // smart : 2015-07-09 Smart Communications, Inc. (SMART) smart // smile : 2014-12-18 Amazon EU S.à r.l. smile // sncf : 2015-02-19 Société Nationale des Chemins de fer Francais S N C F sncf // soccer : 2015-03-26 Foggy Shadow, LLC soccer // social : 2013-11-07 United TLD Holdco Ltd. social // softbank : 2015-07-02 SoftBank Corp. softbank // software : 2014-03-20 software // sohu : 2013-12-19 Sohu.com Limited sohu // solar : 2013-11-07 Ruby Town, LLC solar // solutions : 2013-11-07 Silver Cover, LLC solutions // song : 2015-02-26 Amazon EU S.à r.l. song // sony : 2015-01-08 Sony Corporation sony // soy : 2014-01-23 Charleston Road Registry Inc. soy // space : 2014-04-03 DotSpace Inc. space // spiegel : 2014-02-05 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG spiegel // spot : 2015-02-26 Amazon EU S.à r.l. spot // spreadbetting : 2014-12-11 IG Group Holdings PLC spreadbetting // srl : 2015-05-07 mySRL GmbH srl // srt : 2015-07-30 FCA US LLC. srt // stada : 2014-11-13 STADA Arzneimittel AG stada // staples : 2015-07-30 Staples, Inc. staples // star : 2015-01-08 Star India Private Limited star // starhub : 2015-02-05 StarHub Ltd starhub // statebank : 2015-03-12 STATE BANK OF INDIA statebank // statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company statefarm // statoil : 2014-12-04 Statoil ASA statoil // stc : 2014-10-09 Saudi Telecom Company stc // stcgroup : 2014-10-09 Saudi Telecom Company stcgroup // stockholm : 2014-12-18 Stockholms kommun stockholm // storage : 2014-12-22 Self Storage Company LLC storage // store : 2015-04-09 DotStore Inc. store // stream : 2016-01-08 dot Stream Limited stream // studio : 2015-02-11 studio // study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD study // style : 2014-12-04 Binky Moon, LLC style // sucks : 2014-12-22 Vox Populi Registry Inc. sucks // supplies : 2013-12-19 Atomic Fields, LLC supplies // supply : 2013-12-19 Half Falls, LLC supply // support : 2013-10-24 Grand Orchard, LLC support // surf : 2014-01-09 Top Level Domain Holdings Limited surf // surgery : 2014-03-20 Tin Avenue, LLC surgery // suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION suzuki // swatch : 2015-01-08 The Swatch Group Ltd swatch // swiftcover : 2015-07-23 Swiftcover Insurance Services Limited swiftcover // swiss : 2014-10-16 Swiss Confederation swiss // sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet sydney // symantec : 2014-12-04 Symantec Corporation symantec // systems : 2013-11-07 Dash Cypress, LLC systems // tab : 2014-12-04 Tabcorp Holdings Limited tab // taipei : 2014-07-10 Taipei City Government taipei // talk : 2015-04-09 Amazon EU S.à r.l. talk // taobao : 2015-01-15 Alibaba Group Holding Limited taobao // target : 2015-07-31 Target Domain Holdings, LLC target // tatamotors : 2015-03-12 Tata Motors Ltd tatamotors // tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic" tatar // tattoo : 2013-08-30 Uniregistry, Corp. tattoo // tax : 2014-03-20 Storm Orchard, LLC tax // taxi : 2015-03-19 Pine Falls, LLC taxi // tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. tci // tdk : 2015-06-11 TDK Corporation tdk // team : 2015-03-05 Atomic Lake, LLC team // tech : 2015-01-30 Dot Tech LLC tech // technology : 2013-09-13 Auburn Falls technology // telecity : 2015-02-19 TelecityGroup International Limited telecity // telefonica : 2014-10-16 Telefónica S.A. telefonica // temasek : 2014-08-07 Temasek Holdings (Private) Limited temasek // tennis : 2014-12-04 Cotton Bloom, LLC tennis // teva : 2015-07-02 Teva Pharmaceutical Industries Limited teva // thd : 2015-04-02 Homer TLC, Inc. thd // theater : 2015-03-19 Blue Tigers, LLC theater // theatre : 2015-05-07 theatre // theguardian : 2015-04-30 Guardian News and Media Limited theguardian // tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America tiaa // tickets : 2015-02-05 Accent Media Limited tickets // tienda : 2013-11-14 Victor Manor, LLC tienda // tiffany : 2015-01-30 Tiffany and Company tiffany // tips : 2013-09-20 Corn Willow, LLC tips // tires : 2014-11-07 Dog Edge, LLC tires // tirol : 2014-04-24 punkt Tirol GmbH tirol // tjmaxx : 2015-07-16 The TJX Companies, Inc. tjmaxx // tjx : 2015-07-16 The TJX Companies, Inc. tjx // tkmaxx : 2015-07-16 The TJX Companies, Inc. tkmaxx // tmall : 2015-01-15 Alibaba Group Holding Limited tmall // today : 2013-09-20 Pearl Woods, LLC today // tokyo : 2013-11-13 GMO Registry, Inc. tokyo // tools : 2013-11-21 Pioneer North, LLC tools // top : 2014-03-20 Jiangsu Bangning Science & Technology Co.,Ltd. top // toray : 2014-12-18 Toray Industries, Inc. toray // toshiba : 2014-04-10 TOSHIBA Corporation toshiba // total : 2015-08-06 Total SA total // tours : 2015-01-22 Sugar Station, LLC tours // town : 2014-03-06 Koko Moon, LLC town // toyota : 2015-04-23 TOYOTA MOTOR CORPORATION toyota // toys : 2014-03-06 Pioneer Orchard, LLC toys // trade : 2014-01-23 Elite Registry Limited trade // trading : 2014-12-11 IG Group Holdings PLC trading // training : 2013-11-07 Wild Willow, LLC training // travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc. travelchannel // travelers : 2015-03-26 Travelers TLD, LLC travelers // travelersinsurance : 2015-03-26 Travelers TLD, LLC travelersinsurance // trust : 2014-10-16 trust // trv : 2015-03-26 Travelers TLD, LLC trv // tube : 2015-06-11 Latin American Telecom LLC tube // tui : 2014-07-03 TUI AG tui // tunes : 2015-02-26 Amazon EU S.à r.l. tunes // tushu : 2014-12-18 Amazon EU S.à r.l. tushu // tvs : 2015-02-19 T V SUNDRAM IYENGAR & SONS LIMITED tvs // ubank : 2015-08-20 National Australia Bank Limited ubank // ubs : 2014-12-11 UBS AG ubs // uconnect : 2015-07-30 FCA US LLC. uconnect // unicom : 2015-10-15 China United Network Communications Corporation Limited unicom // university : 2014-03-06 Little Station, LLC university // uno : 2013-09-11 Dot Latin LLC uno // uol : 2014-05-01 UBN INTERNET LTDA. uol // ups : 2015-06-25 UPS Market Driver, Inc. ups // vacations : 2013-12-05 Atomic Tigers, LLC vacations // vana : 2014-12-11 Lifestyle Domain Holdings, Inc. vana // vanguard : 2015-09-03 The Vanguard Group, Inc. vanguard // vegas : 2014-01-16 Dot Vegas, Inc. vegas // ventures : 2013-08-27 Binky Lake, LLC ventures // verisign : 2015-08-13 VeriSign, Inc. verisign // versicherung : 2014-03-20 dotversicherung-registry GmbH versicherung // vet : 2014-03-06 vet // viajes : 2013-10-17 Black Madison, LLC viajes // video : 2014-10-16 video // vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe vig // viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd. viking // villas : 2013-12-05 New Sky, LLC villas // vin : 2015-06-18 Holly Shadow, LLC vin // vip : 2015-01-22 Minds + Machines Group Limited vip // virgin : 2014-09-25 Virgin Enterprises Limited virgin // visa : 2015-07-30 Visa Worldwide Pte. Limited visa // vision : 2013-12-05 Koko Station, LLC vision // vista : 2014-09-18 Vistaprint Limited vista // vistaprint : 2014-09-18 Vistaprint Limited vistaprint // viva : 2014-11-07 Saudi Telecom Company viva // vivo : 2015-07-31 Telefonica Brasil S.A. vivo // vlaanderen : 2014-02-06 DNS.be vzw vlaanderen // vodka : 2013-12-19 Top Level Domain Holdings Limited vodka // volkswagen : 2015-05-14 Volkswagen Group of America Inc. volkswagen // volvo : 2015-11-12 Volvo Holding Sverige Aktiebolag volvo // vote : 2013-11-21 Monolith Registry LLC vote // voting : 2013-11-13 Valuetainment Corp. voting // voto : 2013-11-21 Monolith Registry LLC voto // voyage : 2013-08-27 Ruby House, LLC voyage // vuelos : 2015-03-05 Travel Reservations SRL vuelos // wales : 2014-05-08 Nominet UK wales // walmart : 2015-07-31 Wal-Mart Stores, Inc. walmart // walter : 2014-11-13 Sandvik AB walter // wang : 2013-10-24 Zodiac Leo Limited wang // wanggou : 2014-12-18 Amazon EU S.à r.l. wanggou // warman : 2015-06-18 Weir Group IP Limited warman // watch : 2013-11-14 Sand Shadow, LLC watch // watches : 2014-12-22 Richemont DNS Inc. watches // weather : 2015-01-08 The Weather Channel, LLC weather // weatherchannel : 2015-03-12 The Weather Channel, LLC weatherchannel // webcam : 2014-01-23 dot Webcam Limited webcam // weber : 2015-06-04 Saint-Gobain Weber SA weber // website : 2014-04-03 DotWebsite Inc. website // wed : 2013-10-01 Atgron, Inc. wed // wedding : 2014-04-24 Top Level Domain Holdings Limited wedding // weibo : 2015-03-05 Sina Corporation weibo // weir : 2015-01-29 Weir Group IP Limited weir // whoswho : 2014-02-20 Who's Who Registry whoswho // wien : 2013-10-28 punkt.wien GmbH wien // wiki : 2013-11-07 Top Level Design, LLC wiki // williamhill : 2014-03-13 William Hill Organization Limited williamhill // win : 2014-11-20 First Registry Limited win // windows : 2014-12-18 Microsoft Corporation windows // wine : 2015-06-18 June Station, LLC wine // winners : 2015-07-16 The TJX Companies, Inc. winners // wme : 2014-02-13 William Morris Endeavor Entertainment, LLC wme // wolterskluwer : 2015-08-06 Wolters Kluwer N.V. wolterskluwer // woodside : 2015-07-09 Woodside Petroleum Limited woodside // work : 2013-12-19 Top Level Domain Holdings Limited work // works : 2013-11-14 Little Dynamite, LLC works // world : 2014-06-12 Bitter Fields, LLC world // wow : 2015-10-08 Amazon EU S.à r.l. wow // wtc : 2013-12-19 World Trade Centers Association, Inc. wtc // wtf : 2014-03-06 Hidden Way, LLC wtf // xbox : 2014-12-18 Microsoft Corporation xbox // xerox : 2014-10-24 Xerox DNHC LLC xerox // xfinity : 2015-07-09 Comcast IP Holdings I, LLC xfinity // xihuan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. xihuan // xin : 2014-12-11 Elegant Leader Limited xin // xn--11b4c3d : 2015-01-15 VeriSign Sarl कॉम // xn--1ck2e1b : 2015-02-26 Amazon EU S.à r.l. セール // xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd. 佛山 // xn--30rr7y : 2014-06-12 Excellent First Limited 慈善 // xn--3bst00m : 2013-09-13 Eagle Horizon Limited 集团 // xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED 在线 // xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd. 大众汽车 // xn--3pxu8k : 2015-01-15 VeriSign Sarl 点看 // xn--42c2d9a : 2015-01-15 VeriSign Sarl คอม // xn--45q11c : 2013-11-21 Zodiac Scorpio Limited 八卦 // xn--4gbrim : 2013-10-04 Suhub Electronic Establishment موقع // xn--4gq48lf9j : 2015-07-31 Wal-Mart Stores, Inc. 一号店 // xn--55qw42g : 2013-11-08 China Organizational Name Administration Center 公益 // xn--55qx5d : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) 公司 // xn--5su34j936bgsg : 2015-09-03 Shangri‐La International Hotel Management Limited 香格里拉 // xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited 网站 // xn--6frz82g : 2013-09-23 Afilias Limited 移动 // xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited 我爱你 // xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID) москва // xn--80aqecdr1a : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) католик // xn--80asehdb : 2013-07-14 CORE Association онлайн // xn--80aswg : 2013-07-14 CORE Association сайт // xn--8y0a063a : 2015-03-26 China United Network Communications Corporation Limited 联通 // xn--9dbq2a : 2015-01-15 VeriSign Sarl קום // xn--9et52u : 2014-06-12 RISE VICTORY LIMITED 时尚 // xn--9krt00a : 2015-03-12 Sina Corporation 微博 // xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited 淡马锡 // xn--bck1b9a5dre4c : 2015-02-26 Amazon EU S.à r.l. ファッション // xn--c1avg : 2013-11-14 Public Interest Registry орг // xn--c2br7g : 2015-01-15 VeriSign Sarl नेट // xn--cck2b3b : 2015-02-26 Amazon EU S.à r.l. ストア // xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD 삼성 // xn--czr694b : 2014-01-16 Dot Trademark TLD Holding Company Limted 商标 // xn--czrs0t : 2013-12-19 Wild Island, LLC 商店 // xn--czru2d : 2013-11-21 Zodiac Capricorn Limited 商城 // xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives “The Smart Internet” дети // xn--eckvdtc9d : 2014-12-18 Amazon EU S.à r.l. ポイント // xn--efvy88h : 2014-08-22 Xinhua News Agency Guangdong Branch 新华通讯社广东分社 新闻 // xn--estv75g : 2015-02-19 Industrial and Commercial Bank of China Limited 工行 // xn--fct429k : 2015-04-09 Amazon EU S.à r.l. 家電 // xn--fhbei : 2015-01-15 VeriSign Sarl كوم // xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED 中文网 // xn--fiq64b : 2013-10-14 CITIC Group Corporation 中信 // xn--fjq720a : 2014-05-22 Will Bloom, LLC 娱乐 // xn--flw351e : 2014-07-31 Charleston Road Registry Inc. 谷歌 // xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited 電訊盈科 // xn--g2xx48c : 2015-01-30 Minds + Machines Group Limited 购物 // xn--gckr3f0f : 2015-02-26 Amazon EU S.à r.l. クラウド // xn--gk3at1e : 2015-10-08 Amazon EU S.à r.l. 通販 // xn--hxt814e : 2014-05-15 Zodiac Libra Limited 网店 // xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry संगठन // xn--imr513n : 2014-12-11 Dot Trademark TLD Holding Company Limted 餐厅 // xn--io0a7i : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center) 网络 // xn--j1aef : 2015-01-15 VeriSign Sarl ком // xn--jlq61u9w7b : 2015-01-08 Nokia Corporation 诺基亚 // xn--jvr189m : 2015-02-26 Amazon EU S.à r.l. 食品 // xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V. 飞利浦 // xn--kpu716f : 2014-12-22 Richemont DNS Inc. 手表 // xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd 手机 // xn--mgba3a3ejt : 2014-11-20 Aramco Services Company ارامكو // xn--mgba7c0bbn0a : 2015-05-14 Crescent Holding GmbH العليان // xn--mgbaakc7dvf : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat) اتصالات // xn--mgbab2bd : 2013-10-31 CORE Association بازار // xn--mgbb9fbpob : 2014-12-18 GreenTech Consultancy Company W.L.L. موبايلي // xn--mgbca7dzdo : 2015-07-30 Abu Dhabi Systems and Information Centre ابوظبي // xn--mgbi4ecexp : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) كاثوليك // xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti. همراه // xn--mk1bu44c : 2015-01-15 VeriSign Sarl 닷컴 // xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd. 政府 // xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd. شبكة // xn--ngbe9e0a : 2014-12-04 Kuwait Finance House بيتك // xn--ngbrx : 2015-11-12 League of Arab States عرب // xn--nqv7f : 2013-11-14 Public Interest Registry 机构 // xn--nqv7fs00ema : 2013-11-14 Public Interest Registry 组织机构 // xn--nyqy26a : 2014-11-07 Stable Tone Limited 健康 // xn--p1acf : 2013-12-12 Rusnames Limited рус // xn--pbt977c : 2014-12-22 Richemont DNS Inc. 珠宝 // xn--pssy2u : 2015-01-15 VeriSign Sarl 大拿 // xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc. みんな // xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc. グーグル // xn--rhqv96g : 2013-09-11 Stable Tone Limited 世界 // xn--rovu88b : 2015-02-26 Amazon EU S.à r.l. 書籍 // xn--ses554g : 2014-01-16 网址 // xn--t60b56a : 2015-01-15 VeriSign Sarl 닷넷 // xn--tckwe : 2015-01-15 VeriSign Sarl コム // xn--tiq49xqyj : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication) 天主教 // xn--unup4y : 2013-07-14 Spring Fields, LLC 游戏 // xn--vermgensberater-ctb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG vermögensberater // xn--vermgensberatung-pwb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG vermögensberatung // xn--vhquv : 2013-08-27 Dash McCook, LLC 企业 // xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd. 信息 // xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited 嘉里大酒店 // xn--w4rs40l : 2015-07-30 Kerry Trading Co. Limited 嘉里 // xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd. 广东 // xn--zfr164b : 2013-11-08 China Organizational Name Administration Center 政务 // xperia : 2015-05-14 Sony Mobile Communications AB xperia // xyz : 2013-12-05 XYZ.COM LLC xyz // yachts : 2014-01-09 DERYachts, LLC yachts // yahoo : 2015-04-02 Yahoo! Domain Services Inc. yahoo // yamaxun : 2014-12-18 Amazon EU S.à r.l. yamaxun // yandex : 2014-04-10 YANDEX, LLC yandex // yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD. yodobashi // yoga : 2014-05-29 Top Level Domain Holdings Limited yoga // yokohama : 2013-12-12 GMO Registry, Inc. yokohama // you : 2015-04-09 Amazon EU S.à r.l. you // youtube : 2014-05-01 Charleston Road Registry Inc. youtube // yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD. yun // zappos : 2015-06-25 Amazon EU S.à r.l. zappos // zara : 2014-11-07 Industria de Diseño Textil, S.A. (INDITEX, S.A.) zara // zero : 2014-12-18 Amazon EU S.à r.l. zero // zip : 2014-05-08 Charleston Road Registry Inc. zip // zippo : 2015-07-02 Zadco Company zippo // zone : 2013-11-14 Outer Falls, LLC zone // zuerich : 2014-11-07 Kanton Zürich (Canton of Zurich) zuerich // ===END ICANN DOMAINS=== // ===BEGIN PRIVATE DOMAINS=== // (Note: these are in alphabetical order by company name) // Agnat sp. z o.o. : https://domena.pl // Submitted by Przemyslaw Plewa beep.pl // Alces Software Ltd : http://alces-software.com // Submitted by Mark J. Titorenko *.compute.estate *.alces.network // alwaysdata : https://www.alwaysdata.com // Submitted by Cyril *.alwaysdata.net // Amazon CloudFront : https://aws.amazon.com/cloudfront/ // Submitted by Donavan Miller cloudfront.net // Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/ // Submitted by Luke Wells *.compute.amazonaws.com *.compute-1.amazonaws.com *.compute.amazonaws.com.cn us-east-1.amazonaws.com // Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/ // Submitted by Luke Wells elasticbeanstalk.cn-north-1.amazonaws.com.cn *.elasticbeanstalk.com // Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/ // Submitted by Luke Wells *.elb.amazonaws.com *.elb.amazonaws.com.cn // Amazon S3 : https://aws.amazon.com/s3/ // Submitted by Luke Wells *.s3.amazonaws.com s3-ap-northeast-1.amazonaws.com s3-ap-northeast-2.amazonaws.com s3-ap-south-1.amazonaws.com s3-ap-southeast-1.amazonaws.com s3-ap-southeast-2.amazonaws.com s3-ca-central-1.amazonaws.com s3-eu-central-1.amazonaws.com s3-eu-west-1.amazonaws.com s3-external-1.amazonaws.com s3-fips-us-gov-west-1.amazonaws.com s3-sa-east-1.amazonaws.com s3-us-gov-west-1.amazonaws.com s3-us-east-2.amazonaws.com s3-us-west-1.amazonaws.com s3-us-west-2.amazonaws.com s3.ap-northeast-2.amazonaws.com s3.ap-south-1.amazonaws.com s3.cn-north-1.amazonaws.com.cn s3.ca-central-1.amazonaws.com s3.eu-central-1.amazonaws.com s3.us-east-2.amazonaws.com s3.dualstack.ap-northeast-1.amazonaws.com s3.dualstack.ap-northeast-2.amazonaws.com s3.dualstack.ap-south-1.amazonaws.com s3.dualstack.ap-southeast-1.amazonaws.com s3.dualstack.ap-southeast-2.amazonaws.com s3.dualstack.ca-central-1.amazonaws.com s3.dualstack.eu-central-1.amazonaws.com s3.dualstack.eu-west-1.amazonaws.com s3.dualstack.sa-east-1.amazonaws.com s3.dualstack.us-east-1.amazonaws.com s3.dualstack.us-east-2.amazonaws.com s3-website-us-east-1.amazonaws.com s3-website-us-west-1.amazonaws.com s3-website-us-west-2.amazonaws.com s3-website-ap-northeast-1.amazonaws.com s3-website-ap-southeast-1.amazonaws.com s3-website-ap-southeast-2.amazonaws.com s3-website-eu-west-1.amazonaws.com s3-website-sa-east-1.amazonaws.com s3-website.ap-northeast-2.amazonaws.com s3-website.ap-south-1.amazonaws.com s3-website.ca-central-1.amazonaws.com s3-website.eu-central-1.amazonaws.com s3-website.us-east-2.amazonaws.com // Amune : https://amune.org/ // Submitted by Team Amune t3l3p0rt.net tele.amune.org // Aptible : https://www.aptible.com/ // Submitted by Thomas Orozco on-aptible.com // Asociación Amigos de la Informática "Euskalamiga" : http://encounter.eus/ // Submitted by Hector Martin user.party.eus // Association potager.org : https://potager.org/ // Submitted by Lunar pimienta.org poivron.org potager.org sweetpepper.org // ASUSTOR Inc. : http://www.asustor.com // Submitted by Vincent Tseng myasustor.com // AVM : https://avm.de // Submitted by Andreas Weise myfritz.net // backplane : https://www.backplane.io // Submitted by Anthony Voutas backplaneapp.io // BetaInABox // Submitted by Adrian betainabox.com // BinaryLane : http://www.binarylane.com // Submitted by Nathan O'Sullivan bnr.la // Boxfuse : https://boxfuse.com // Submitted by Axel Fontaine boxfuse.io // BrowserSafetyMark // Submitted by Dave Tharp browsersafetymark.io // callidomus: https://www.callidomus.com/ // Submitted by Marcus Popp mycd.eu // CentralNic : http://www.centralnic.com/names/domains // Submitted by registry ae.org ar.com br.com cn.com com.de com.se de.com eu.com gb.com gb.net hu.com hu.net jp.net jpn.com kr.com mex.com no.com qc.com ru.com sa.com se.com se.net uk.com uk.net us.com uy.com za.bz za.com // Africa.com Web Solutions Ltd : https://registry.africa.com // Submitted by Gavin Brown africa.com // iDOT Services Limited : http://www.domain.gr.com // Submitted by Gavin Brown gr.com // Radix FZC : http://domains.in.net // Submitted by Gavin Brown in.net // US REGISTRY LLC : http://us.org // Submitted by Gavin Brown us.org // co.com Registry, LLC : https://registry.co.com // Submitted by Gavin Brown co.com // c.la : http://www.c.la/ c.la // certmgr.org : https://certmgr.org // Submitted by B. Blechschmidt certmgr.org // Citrix : https://citrix.com // Submitted by Alex Stoddard xenapponazure.com // ClearVox : http://www.clearvox.nl/ // Submitted by Leon Rowland virtueeldomein.nl // cloudControl : https://www.cloudcontrol.com/ // Submitted by Tobias Wilken cloudcontrolled.com cloudcontrolapp.com // co.ca : http://registry.co.ca/ co.ca // i-registry s.r.o. : http://www.i-registry.cz/ // Submitted by Martin Semrad co.cz // CDN77.com : http://www.cdn77.com // Submitted by Jan Krpes c.cdn77.org cdn77-ssl.net r.cdn77.net rsc.cdn77.org ssl.origin.cdn77-secure.org // Cloud DNS Ltd : http://www.cloudns.net // Submitted by Aleksander Hristov cloudns.asia cloudns.biz cloudns.club cloudns.cc cloudns.eu cloudns.in cloudns.info cloudns.org cloudns.pro cloudns.pw cloudns.us // CoDNS B.V. co.nl co.no // Commerce Guys, SAS // Submitted by Damien Tournoud *.platform.sh // COSIMO GmbH http://www.cosimo.de // Submitted by Rene Marticke dyn.cosidns.de dynamisches-dns.de dnsupdater.de internet-dns.de l-o-g-i-n.de dynamic-dns.info feste-ip.net knx-server.net static-access.net // Craynic, s.r.o. : http://www.craynic.com/ // Submitted by Ales Krajnik realm.cz // Cryptonomic : https://cryptonomic.net/ // Submitted by Andrew Cady *.cryptonomic.net // Cupcake : https://cupcake.io/ // Submitted by Jonathan Rudenberg cupcake.is // cyon GmbH : https://www.cyon.ch/ // Submitted by Dominic Luechinger cyon.link cyon.site // Daplie, Inc : https://daplie.com // Submitted by AJ ONeal daplie.me // Dansk.net : http://www.dansk.net/ // Submitted by Anani Voule biz.dk co.dk firm.dk reg.dk store.dk // deSEC : https://desec.io/ // Submitted by Peter Thomassen dedyn.io // DNShome : https://www.dnshome.de/ // Submitted by Norbert Auler dnshome.de // DreamHost : http://www.dreamhost.com/ // Submitted by Andrew Farmer dreamhosters.com // Drobo : http://www.drobo.com/ // Submitted by Ricardo Padilha mydrobo.com // Drud Holdings, LLC. : https://www.drud.com/ // Submitted by Kevin Bridges drud.io drud.us // DuckDNS : http://www.duckdns.org/ // Submitted by Richard Harper duckdns.org // dy.fi : http://dy.fi/ // Submitted by Heikki Hannikainen dy.fi tunk.org // DynDNS.com : http://www.dyndns.com/services/dns/dyndns/ dyndns-at-home.com dyndns-at-work.com dyndns-blog.com dyndns-free.com dyndns-home.com dyndns-ip.com dyndns-mail.com dyndns-office.com dyndns-pics.com dyndns-remote.com dyndns-server.com dyndns-web.com dyndns-wiki.com dyndns-work.com dyndns.biz dyndns.info dyndns.org dyndns.tv at-band-camp.net ath.cx barrel-of-knowledge.info barrell-of-knowledge.info better-than.tv blogdns.com blogdns.net blogdns.org blogsite.org boldlygoingnowhere.org broke-it.net buyshouses.net cechire.com dnsalias.com dnsalias.net dnsalias.org dnsdojo.com dnsdojo.net dnsdojo.org does-it.net doesntexist.com doesntexist.org dontexist.com dontexist.net dontexist.org doomdns.com doomdns.org dvrdns.org dyn-o-saur.com dynalias.com dynalias.net dynalias.org dynathome.net dyndns.ws endofinternet.net endofinternet.org endoftheinternet.org est-a-la-maison.com est-a-la-masion.com est-le-patron.com est-mon-blogueur.com for-better.biz for-more.biz for-our.info for-some.biz for-the.biz forgot.her.name forgot.his.name from-ak.com from-al.com from-ar.com from-az.net from-ca.com from-co.net from-ct.com from-dc.com from-de.com from-fl.com from-ga.com from-hi.com from-ia.com from-id.com from-il.com from-in.com from-ks.com from-ky.com from-la.net from-ma.com from-md.com from-me.org from-mi.com from-mn.com from-mo.com from-ms.com from-mt.com from-nc.com from-nd.com from-ne.com from-nh.com from-nj.com from-nm.com from-nv.com from-ny.net from-oh.com from-ok.com from-or.com from-pa.com from-pr.com from-ri.com from-sc.com from-sd.com from-tn.com from-tx.com from-ut.com from-va.com from-vt.com from-wa.com from-wi.com from-wv.com from-wy.com ftpaccess.cc fuettertdasnetz.de game-host.org game-server.cc getmyip.com gets-it.net go.dyndns.org gotdns.com gotdns.org groks-the.info groks-this.info ham-radio-op.net here-for-more.info hobby-site.com hobby-site.org home.dyndns.org homedns.org homeftp.net homeftp.org homeip.net homelinux.com homelinux.net homelinux.org homeunix.com homeunix.net homeunix.org iamallama.com in-the-band.net is-a-anarchist.com is-a-blogger.com is-a-bookkeeper.com is-a-bruinsfan.org is-a-bulls-fan.com is-a-candidate.org is-a-caterer.com is-a-celticsfan.org is-a-chef.com is-a-chef.net is-a-chef.org is-a-conservative.com is-a-cpa.com is-a-cubicle-slave.com is-a-democrat.com is-a-designer.com is-a-doctor.com is-a-financialadvisor.com is-a-geek.com is-a-geek.net is-a-geek.org is-a-green.com is-a-guru.com is-a-hard-worker.com is-a-hunter.com is-a-knight.org is-a-landscaper.com is-a-lawyer.com is-a-liberal.com is-a-libertarian.com is-a-linux-user.org is-a-llama.com is-a-musician.com is-a-nascarfan.com is-a-nurse.com is-a-painter.com is-a-patsfan.org is-a-personaltrainer.com is-a-photographer.com is-a-player.com is-a-republican.com is-a-rockstar.com is-a-socialist.com is-a-soxfan.org is-a-student.com is-a-teacher.com is-a-techie.com is-a-therapist.com is-an-accountant.com is-an-actor.com is-an-actress.com is-an-anarchist.com is-an-artist.com is-an-engineer.com is-an-entertainer.com is-by.us is-certified.com is-found.org is-gone.com is-into-anime.com is-into-cars.com is-into-cartoons.com is-into-games.com is-leet.com is-lost.org is-not-certified.com is-saved.org is-slick.com is-uberleet.com is-very-bad.org is-very-evil.org is-very-good.org is-very-nice.org is-very-sweet.org is-with-theband.com isa-geek.com isa-geek.net isa-geek.org isa-hockeynut.com issmarterthanyou.com isteingeek.de istmein.de kicks-ass.net kicks-ass.org knowsitall.info land-4-sale.us lebtimnetz.de leitungsen.de likes-pie.com likescandy.com merseine.nu mine.nu misconfused.org mypets.ws myphotos.cc neat-url.com office-on-the.net on-the-web.tv podzone.net podzone.org readmyblog.org saves-the-whales.com scrapper-site.net scrapping.cc selfip.biz selfip.com selfip.info selfip.net selfip.org sells-for-less.com sells-for-u.com sells-it.net sellsyourhome.org servebbs.com servebbs.net servebbs.org serveftp.net serveftp.org servegame.org shacknet.nu simple-url.com space-to-rent.com stuff-4-sale.org stuff-4-sale.us teaches-yoga.com thruhere.net traeumtgerade.de webhop.biz webhop.info webhop.net webhop.org worse-than.tv writesthisblog.com // ddnss.de : https://www.ddnss.de/ // Submitted by Robert Niedziela ddnss.de dyn.ddnss.de dyndns.ddnss.de dyndns1.de dyn-ip24.de home-webserver.de dyn.home-webserver.de myhome-server.de ddnss.org // dynv6 : https://dynv6.com // Submitted by Dominik Menke 2016-01-18 dynv6.net // E4YOU spol. s.r.o. : https://e4you.cz/ // Submitted by Vladimir Dudr e4.cz // Enonic : http://enonic.com/ // Submitted by Erik Kaareng-Sunde enonic.io customer.enonic.io // EU.org https://eu.org/ // Submitted by Pierre Beyssac eu.org al.eu.org asso.eu.org at.eu.org au.eu.org be.eu.org bg.eu.org ca.eu.org cd.eu.org ch.eu.org cn.eu.org cy.eu.org cz.eu.org de.eu.org dk.eu.org edu.eu.org ee.eu.org es.eu.org fi.eu.org fr.eu.org gr.eu.org hr.eu.org hu.eu.org ie.eu.org il.eu.org in.eu.org int.eu.org is.eu.org it.eu.org jp.eu.org kr.eu.org lt.eu.org lu.eu.org lv.eu.org mc.eu.org me.eu.org mk.eu.org mt.eu.org my.eu.org net.eu.org ng.eu.org nl.eu.org no.eu.org nz.eu.org paris.eu.org pl.eu.org pt.eu.org q-a.eu.org ro.eu.org ru.eu.org se.eu.org si.eu.org sk.eu.org tr.eu.org uk.eu.org us.eu.org // Evennode : http://www.evennode.com/ // Submitted by Michal Kralik eu-1.evennode.com eu-2.evennode.com us-1.evennode.com us-2.evennode.com // Facebook, Inc. // Submitted by Peter Ruibal apps.fbsbx.com // Fastly Inc. http://www.fastly.com/ // Submitted by Vladimir Vuksan a.ssl.fastly.net b.ssl.fastly.net global.ssl.fastly.net a.prod.fastly.net global.prod.fastly.net // Featherhead : https://featherhead.xyz/ // Submitted by Simon Menke fhapp.xyz // Firebase, Inc. // Submitted by Chris Raynor firebaseapp.com // Flynn : https://flynn.io // Submitted by Jonathan Rudenberg flynnhub.com // Freebox : http://www.freebox.fr // Submitted by Romain Fliedel freebox-os.com freeboxos.com fbx-os.fr fbxos.fr freebox-os.fr freeboxos.fr // Fusion Intranet : https://www.fusion-intranet.com // Submitted by Matthias Burtscher myfusion.cloud // Futureweb OG : http://www.futureweb.at // Submitted by Andreas Schnederle-Wagner futurehosting.at futuremailing.at *.ex.ortsinfo.at *.kunden.ortsinfo.at *.statics.cloud // GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains // Submitted by David Illsley service.gov.uk // GitHub, Inc. // Submitted by Patrick Toomey github.io githubusercontent.com githubcloud.com *.api.githubcloud.com *.ext.githubcloud.com gist.githubcloud.com *.githubcloudusercontent.com // GitLab, Inc. // Submitted by Alex Hanselka gitlab.io // UKHomeOffice : https://www.gov.uk/government/organisations/home-office // Submitted by Jon Shanks homeoffice.gov.uk // GlobeHosting, Inc. // Submitted by Zoltan Egresi ro.im shop.ro // GoIP DNS Services : http://www.goip.de // Submitted by Christian Poulter goip.de // Google, Inc. // Submitted by Eduardo Vela *.0emm.com appspot.com blogspot.ae blogspot.al blogspot.am blogspot.ba blogspot.be blogspot.bg blogspot.bj blogspot.ca blogspot.cf blogspot.ch blogspot.cl blogspot.co.at blogspot.co.id blogspot.co.il blogspot.co.ke blogspot.co.nz blogspot.co.uk blogspot.co.za blogspot.com blogspot.com.ar blogspot.com.au blogspot.com.br blogspot.com.by blogspot.com.co blogspot.com.cy blogspot.com.ee blogspot.com.eg blogspot.com.es blogspot.com.mt blogspot.com.ng blogspot.com.tr blogspot.com.uy blogspot.cv blogspot.cz blogspot.de blogspot.dk blogspot.fi blogspot.fr blogspot.gr blogspot.hk blogspot.hr blogspot.hu blogspot.ie blogspot.in blogspot.is blogspot.it blogspot.jp blogspot.kr blogspot.li blogspot.lt blogspot.lu blogspot.md blogspot.mk blogspot.mr blogspot.mx blogspot.my blogspot.nl blogspot.no blogspot.pe blogspot.pt blogspot.qa blogspot.re blogspot.ro blogspot.rs blogspot.ru blogspot.se blogspot.sg blogspot.si blogspot.sk blogspot.sn blogspot.td blogspot.tw blogspot.ug blogspot.vn cloudfunctions.net codespot.com googleapis.com googlecode.com pagespeedmobilizer.com publishproxy.com withgoogle.com withyoutube.com // Hashbang : https://hashbang.sh hashbang.sh // Hasura : https://hasura.io // Submitted by Shahidh K Muhammed hasura-app.io // Hepforge : https://www.hepforge.org // Submitted by David Grellscheid hepforge.org // Heroku : https://www.heroku.com/ // Submitted by Tom Maher herokuapp.com herokussl.com // iki.fi // Submitted by Hannu Aronsson iki.fi // info.at : http://www.info.at/ biz.at info.at // Interlegis : http://www.interlegis.leg.br // Submitted by Gabriel Ferreira ac.leg.br al.leg.br am.leg.br ap.leg.br ba.leg.br ce.leg.br df.leg.br es.leg.br go.leg.br ma.leg.br mg.leg.br ms.leg.br mt.leg.br pa.leg.br pb.leg.br pe.leg.br pi.leg.br pr.leg.br rj.leg.br rn.leg.br ro.leg.br rr.leg.br rs.leg.br sc.leg.br se.leg.br sp.leg.br to.leg.br // Joyent : https://www.joyent.com/ // Submitted by Brian Bennett *.triton.zone *.cns.joyent.com // JS.ORG : http://dns.js.org // Submitted by Stefan Keim js.org // Keyweb AG : https://www.keyweb.de // Submitted by Martin Dannehl keymachine.de // KnightPoint Systems, LLC : http://www.knightpoint.com/ // Submitted by Roy Keene knightpoint.systems // .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf co.krd edu.krd // Magento Commerce // Submitted by Damien Tournoud *.magentosite.cloud // Meteor Development Group : https://www.meteor.com/hosting // Submitted by Pierre Carrier meteorapp.com eu.meteorapp.com // Michau Enterprises Limited : http://www.co.pl/ co.pl // Microsoft : http://microsoft.com // Submitted by Barry Dorrans azurewebsites.net azure-mobile.net cloudapp.net // Mozilla Foundation : https://mozilla.org/ // Submitted by glob bmoattachments.org // Neustar Inc. // Submitted by Trung Tran 4u.com // ngrok : https://ngrok.com/ // Submitted by Alan Shreve ngrok.io // NFSN, Inc. : https://www.NearlyFreeSpeech.NET/ // Submitted by Jeff Wheelhouse nfshost.com // nsupdate.info : https://www.nsupdate.info/ // Submitted by Thomas Waldmann nsupdate.info nerdpol.ovh // No-IP.com : https://noip.com/ // Submitted by Deven Reza blogsyte.com brasilia.me cable-modem.org ciscofreak.com collegefan.org couchpotatofries.org damnserver.com ddns.me ditchyourip.com dnsfor.me dnsiskinky.com dvrcam.info dynns.com eating-organic.net fantasyleague.cc geekgalaxy.com golffan.us health-carereform.com homesecuritymac.com homesecuritypc.com hopto.me ilovecollege.info loginto.me mlbfan.org mmafan.biz myactivedirectory.com mydissent.net myeffect.net mymediapc.net mypsx.net mysecuritycamera.com mysecuritycamera.net mysecuritycamera.org net-freaks.com nflfan.org nhlfan.net no-ip.ca no-ip.co.uk no-ip.net noip.us onthewifi.com pgafan.net point2this.com pointto.us privatizehealthinsurance.net quicksytes.com read-books.org securitytactics.com serveexchange.com servehumour.com servep2p.com servesarcasm.com stufftoread.com ufcfan.org unusualperson.com workisboring.com 3utilities.com bounceme.net ddns.net ddnsking.com gotdns.ch hopto.org myftp.biz myftp.org myvnc.com no-ip.biz no-ip.info no-ip.org noip.me redirectme.net servebeer.com serveblog.net servecounterstrike.com serveftp.com servegame.com servehalflife.com servehttp.com serveirc.com serveminecraft.net servemp3.com servepics.com servequake.com sytes.net webhop.me zapto.org // NYC.mn : http://www.information.nyc.mn // Submitted by Matthew Brown nyc.mn // One Fold Media : http://www.onefoldmedia.com/ // Submitted by Eddie Jones nid.io // OpenCraft GmbH : http://opencraft.com/ // Submitted by Sven Marnach opencraft.hosting // Opera Software, A.S.A. // Submitted by Yngve Pettersen operaunite.com // OutSystems // Submitted by Duarte Santos outsystemscloud.com // OwnProvider : http://www.ownprovider.com // Submitted by Jan Moennich ownprovider.com // oy.lc // Submitted by Charly Coste oy.lc // Pagefog : https://pagefog.com/ // Submitted by Derek Myers pgfog.com // Pagefront : https://www.pagefronthq.com/ // Submitted by Jason Kriss pagefrontapp.com // .pl domains (grandfathered) art.pl gliwice.pl krakow.pl poznan.pl wroc.pl zakopane.pl // Pantheon Systems, Inc. : https://pantheon.io/ // Submitted by Gary Dylina pantheonsite.io gotpantheon.com // Peplink | Pepwave : http://peplink.com/ // Submitted by Steve Leung mypep.link // Planet-Work : https://www.planet-work.com/ // Submitted by Frédéric VANNIÈRE on-web.fr // prgmr.com : https://prgmr.com/ // Submitted by Sarah Newman xen.prgmr.com // priv.at : http://www.nic.priv.at/ // Submitted by registry priv.at // Protonet GmbH : http://protonet.io // Submitted by Martin Meier protonet.io // Publication Presse Communication SARL : https://ppcom.fr // Submitted by Yaacov Akiba Slama chirurgiens-dentistes-en-france.fr // QA2 // Submitted by Daniel Dent (https://www.danieldent.com/) qa2.com // QNAP System Inc : https://www.qnap.com // Submitted by Nick Chang dev-myqnapcloud.com alpha-myqnapcloud.com myqnapcloud.com // Rackmaze LLC : https://www.rackmaze.com // Submitted by Kirill Pertsev rackmaze.com rackmaze.net // Red Hat, Inc. OpenShift : https://openshift.redhat.com/ // Submitted by Tim Kramer rhcloud.com // RethinkDB : https://www.rethinkdb.com/ // Submitted by Chris Kastorff hzc.io // Revitalised Limited : http://www.revitalised.co.uk // Submitted by Jack Price wellbeingzone.eu ptplus.fit wellbeingzone.co.uk // Sandstorm Development Group, Inc. : https://sandcats.io/ // Submitted by Asheesh Laroia sandcats.io // SBE network solutions GmbH : https://www.sbe.de/ // Submitted by Norman Meilick logoip.de logoip.com // Securepoint GmbH : https://www.securepoint.de // Submitted by Erik Anders firewall-gateway.com firewall-gateway.de my-gateway.de my-router.de spdns.de spdns.eu firewall-gateway.net my-firewall.org myfirewall.org spdns.org // Service Online LLC : http://drs.ua/ // Submitted by Serhii Bulakh biz.ua co.ua pp.ua // ShiftEdit : https://shiftedit.net/ // Submitted by Adam Jimenez shiftedit.io // Shopblocks : http://www.shopblocks.com/ // Submitted by Alex Bowers myshopblocks.com // SinaAppEngine : http://sae.sina.com.cn/ // Submitted by SinaAppEngine 1kapp.com appchizi.com applinzi.com sinaapp.com vipsinaapp.com // Skyhat : http://www.skyhat.io // Submitted by Shante Adam bounty-full.com alpha.bounty-full.com beta.bounty-full.com // staticland : https://static.land // Submitted by Seth Vincent static.land dev.static.land sites.static.land // SourceLair PC : https://www.sourcelair.com // Submitted by Antonis Kalipetis apps.lair.io *.stolos.io // SpaceKit : https://www.spacekit.io/ // Submitted by Reza Akhavan spacekit.io // Stackspace : https://www.stackspace.io/ // Submitted by Lina He stackspace.space // Synology, Inc. : https://www.synology.com/ // Submitted by Rony Weng diskstation.me dscloud.biz dscloud.me dscloud.mobi dsmynas.com dsmynas.net dsmynas.org familyds.com familyds.net familyds.org i234.me myds.me synology.me // TAIFUN Software AG : http://taifun-software.de // Submitted by Bjoern Henke taifun-dns.de // TASK geographical domains (www.task.gda.pl/uslugi/dns) gda.pl gdansk.pl gdynia.pl med.pl sopot.pl // TownNews.com : http://www.townnews.com // Submitted by Dustin Ward bloxcms.com townnews-staging.com // TransIP : htts://www.transip.nl // Submitted by Rory Breuk *.transurl.be *.transurl.eu *.transurl.nl // TuxFamily : http://tuxfamily.org // Submitted by TuxFamily administrators tuxfamily.org // TwoDNS : https://www.twodns.de/ // Submitted by TwoDNS-Support dd-dns.de diskstation.eu diskstation.org dray-dns.de draydns.de dyn-vpn.de dynvpn.de mein-vigor.de my-vigor.de my-wan.de syno-ds.de synology-diskstation.de synology-ds.de // UDR Limited : http://www.udr.hk.com // Submitted by registry hk.com hk.org ltd.hk inc.hk // .US // Submitted by Ed Moore lib.de.us // Viprinet Europe GmbH : http://www.viprinet.com // Submitted by Simon Kissel router.management // Wikimedia Labs : https://wikitech.wikimedia.org // Submitted by Yuvi Panda wmflabs.org // Yola : https://www.yola.com/ // Submitted by Stefano Rivera yolasite.com // Yombo : https://yombo.net // Submitted by Mitch Schwenk ybo.faith yombo.me homelink.one ybo.party ybo.review ybo.science ybo.trade // ZaNiC : http://www.za.net/ // Submitted by registry za.net za.org // Zeit, Inc. : https://zeit.domains/ // Submitted by Olli Vanhoja now.sh // 1GB LLC : https://www.1gb.ua/ // Submitted by 1GB LLC cc.ua inf.ua ltd.ua // ===END PRIVATE DOMAINS=== mailman-3.1.1/src/mailman/rules/data/__init__.py0000664000175000017500000000000013066532160022623 0ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/no_senders.py0000664000175000017500000000300313203223435022313 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Membership related rules.""" from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class NoSenders: """The message has no senders rule.""" name = 'no-senders' description = _('Match messages with no valid senders.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" if msg.sender: return False else: msgdata['moderation_sender'] = 'N/A' with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('The message has no valid senders')) return True mailman-3.1.1/src/mailman/rules/approved.py0000664000175000017500000001342313066532160022010 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Look for moderator pre-approval.""" import re from email.iterators import typed_subpart_iterator from mailman.config import config from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer EMPTYSTRING = '' HEADERS = [ 'approve', 'approved', 'x-approve', 'x-approved', ] @public @implementer(IRule) class Approved: """Look for moderator pre-approval.""" name = 'approved' description = _('The message has a matching Approve or Approved header.') record = True def _get_password(self, msg, missing): for header in HEADERS: password = msg.get(header, missing) if password is not missing: return password return missing def check(self, mlist, msg, msgdata): """See `IRule`.""" if mlist.moderator_password is None: return False # See if the message has an Approved or Approve header with a valid # moderator password. Also look at the first non-whitespace line in # the file to see if it looks like an Approved header. missing = object() password = self._get_password(msg, missing) if password is missing: # Find the first text/plain part in the message part = None stripped = False payload = None for part in typed_subpart_iterator(msg, 'text', 'plain'): payload = part.get_payload(decode=True) break if payload is not None: charset = part.get_content_charset('us-ascii') try: # Do the decoding inside the try/except so that if the # charset is unknown, we'll just drop back to ascii. payload = payload.decode(charset, 'replace') except LookupError: # Unknown or empty charset. payload = payload.decode('us-ascii', 'replace') line = '' lines = payload.splitlines(True) for lineno, line in enumerate(lines): if line.strip() != '': break if ':' in line: header, value = line.split(':', 1) if header.lower() in HEADERS: password = value.strip() # Now strip the first line from the payload so the # password doesn't leak. del lines[lineno] reset_payload(part, EMPTYSTRING.join(lines)) stripped = True if stripped: # Now try all the text parts in case it's # multipart/alternative with the approved line in HTML or # other text part. We make a pattern from the Approved line # and delete it from all text/* parts in which we find it. It # would be better to just iterate forward, but email # compatability for pre Python 2.2 returns a list, not a true # iterator. # # This will process all the multipart/alternative parts in the # message as well as all other text parts. We shouldn't find # the pattern outside the multipart/alternative parts, but if # we do, it is probably best to delete it anyway as it does # contain the password. # # Make a pattern to delete. We can't just delete a line # because line of HTML or other fancy text may include # additional message text. This pattern works with HTML. It # may not work with rtf or whatever else is possible. pattern = header + ':(\s| )*' + re.escape(password) for part in typed_subpart_iterator(msg, 'text'): payload = part.get_payload() if payload is not None: if re.search(pattern, payload): reset_payload(part, re.sub(pattern, '', payload)) else: for header in HEADERS: del msg[header] if password is missing: return False is_valid, new_hash = config.password_context.verify( password, mlist.moderator_password) if is_valid and new_hash: # Hash algorithm migration. mlist.moderator_password = new_hash return is_valid def reset_payload(part, payload): # Set decoded payload maintaining content-type, charset, format and delsp. charset = part.get_content_charset() or 'us-ascii' content_type = part.get_content_type() format = part.get_param('format') delsp = part.get_param('delsp') del part['content-transfer-encoding'] del part['content-type'] part.set_payload(payload, charset) part.set_type(content_type) if format: part.set_param('Format', format) if delsp: part.set_param('DelSp', delsp) mailman-3.1.1/src/mailman/rules/implicit_dest.py0000664000175000017500000000766313203223435023025 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The implicit destination rule.""" import re from contextlib import suppress from email.utils import getaddresses from mailman.core.i18n import _ from mailman.interfaces.mailinglist import IAcceptableAliasSet from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class ImplicitDestination: """The implicit destination rule.""" name = 'implicit-dest' description = _('Catch messages with implicit destination.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" # Implicit destination checking must be enabled in the mailing list. if not mlist.require_explicit_destination: return False # Messages gated from NNTP will always have an implicit destination so # are never checked. if msgdata.get('fromusenet'): return False # Calculate the list of acceptable aliases. If the alias starts with # a caret (i.e. ^), then it's a regular expression to match against. aliases = set() alias_patterns = set() # Adapt the mailing list to the appropriate interface. alias_set = IAcceptableAliasSet(mlist) for alias in alias_set.aliases: if alias.startswith('^'): alias_patterns.add(alias) else: aliases.add(alias) # Add the list's posting address, i.e. the explicit address, to the # set of acceptable aliases. aliases.add(mlist.posting_address) # Look at all the recipients. If the recipient is any acceptable # alias (or the explicit posting address), then this rule does not # match. If not, then add it to the set of recipients we'll check # against the alias patterns later. recipients = set() for header in ('to', 'cc', 'resent-to', 'resent-cc'): for fullname, address in getaddresses(msg.get_all(header, [])): if isinstance(address, bytes): address = address.decode('ascii') address = address.lower() if address in aliases: return False recipients.add(address) # Now for all alias patterns, see if any of the recipients matches a # pattern. If so, then this rule does not match. for pattern in alias_patterns: escaped = re.escape(pattern) for recipient in recipients: try: if re.match(pattern, recipient, re.IGNORECASE): return False except re.error: # The pattern is a malformed regular expression. Try # matching again with the pattern escaped. with suppress(re.error): if re.match(escaped, recipient, re.IGNORECASE): return False # Nothing matched. msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('Message has implicit destination')) return True mailman-3.1.1/src/mailman/rules/banned_address.py0000664000175000017500000000331213203223435023113 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Banned addresses rule.""" from mailman.core.i18n import _ from mailman.interfaces.bans import IBanManager from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class BannedAddress: """The banned address rule.""" name = 'banned-address' description = _('Match messages sent by banned addresses.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" ban_manager = IBanManager(mlist) for sender in msg.senders: if ban_manager.is_banned(sender): msgdata['moderation_sender'] = sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( (_('Message sender {} is banned from this list'), sender)) return True return False mailman-3.1.1/src/mailman/rules/max_size.py0000664000175000017500000000352613203223435022005 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The maximum message size rule.""" from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class MaximumSize: """The implicit destination rule.""" name = 'max-size' description = _('Catch messages that are bigger than a specified maximum.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" if mlist.max_message_size == 0: return False assert hasattr(msg, 'original_size'), ( 'Message was not sized on initial parsing.') # The maximum size is specified in 1024 bytes. if msg.original_size / 1024.0 > mlist.max_message_size: msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( (_('The message is larger than the {} KB maximum size'), mlist.max_message_size)) return True return False mailman-3.1.1/src/mailman/rules/no_subject.py0000664000175000017500000000322113203223435022311 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The no-Subject header rule.""" from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class NoSubject: """The no-Subject rule.""" name = 'no-subject' description = _('Catch messages with no, or empty, Subject headers.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" # Convert the header value to a str because it may be an # email.header.Header instance. subject = str(msg.get('subject', '')).strip() if subject == '': msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('Message has no subject')) return True return False mailman-3.1.1/src/mailman/rules/loop.py0000664000175000017500000000325213203223435021133 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Look for a posting loop.""" from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class Loop: """Look for a posting loop.""" name = 'loop' description = _('Look for a posting loop.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" # Has this message already been posted to this list? list_posts = set(value.strip().lower() for value in msg.get_all('list-post', [])) if mlist.posting_address in list_posts: msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('Message has already been posted to this list')) return True return False mailman-3.1.1/src/mailman/rules/tests/0000775000175000017500000000000013204154702020751 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/tests/data/0000775000175000017500000000000013204154702021662 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/tests/data/org_domain.txt0000664000175000017500000000074413066532160024552 0ustar maxkingmaxking00000000000000// Test data for dmarc organizational domains. // There are just a few domain entries here for testing purposes. // biz : https://en.wikipedia.org/wiki/.biz biz // com : https://en.wikipedia.org/wiki/.com com // org : https://en.wikipedia.org/wiki/.org org // jp geographic type names // http://jprs.jp/doc/rule/saisoku-1.html *.kobe.jp !city.kobe.jp // A line with a trailing comment for testing co.uk some nonsense // A line with leading white space (ignored) example.biz mailman-3.1.1/src/mailman/rules/tests/data/__init__.py0000664000175000017500000000000013066532160023765 0ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/tests/test_loop.py0000664000175000017500000000316713203223435023341 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `loop` rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.rules import loop from mailman.testing.helpers import specialized_message_from_string as mfs from mailman.testing.layers import ConfigLayer class TestLoop(unittest.TestCase): """Test the loop rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_loop_returns_reason(self): # Ensure loop rule returns a reason. msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Subject List-Post: test@example.com Message-ID: A message body. """) rule = loop.Loop() msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], ['Message has already been posted to this list']) mailman-3.1.1/src/mailman/rules/tests/test_suspicious.py0000664000175000017500000000370013203223435024567 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `suspicious` rule.""" import unittest from email.header import Header from mailman.app.lifecycle import create_list from mailman.email.message import Message from mailman.rules import suspicious from mailman.testing.layers import ConfigLayer class TestSuspicious(unittest.TestCase): """Test the suspicious rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') self._rule = suspicious.SuspiciousHeader() def test_header_instance(self): msg = Message() msg['From'] = Header('user@example.com') self._mlist.bounce_matching_headers = 'from: spam@example.com' result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_suspicious_returns_reason(self): msg = Message() msg['From'] = Header('spam@example.com') self._mlist.bounce_matching_headers = 'from: spam@example.com' msgdata = {} result = self._rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual( msgdata['moderation_reasons'], [('Header "{}" matched a bounce_matching_header line', 'spam@example.com')] ) mailman-3.1.1/src/mailman/rules/tests/test_max_recipients.py0000664000175000017500000000337713203223435025405 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `max_recipients` rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.rules import max_recipients from mailman.testing.helpers import specialized_message_from_string as mfs from mailman.testing.layers import ConfigLayer class TestMaximumRecipients(unittest.TestCase): """Test the max_recipients rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_max_recipients_returns_reason(self): # Ensure max_recipients rule returns a reason. msg = mfs("""\ From: anne@example.com To: test@example.com Cc: anne@example.com, bill@example.com Subject: A Subject Message-ID: A message body. """) rule = max_recipients.MaximumRecipients() self._mlist.max_num_recipients = 2 msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], [('Message has more than {} recipients', 2)]) mailman-3.1.1/src/mailman/rules/tests/test_moderation.py0000664000175000017500000003115113203223435024523 0ustar maxkingmaxking00000000000000# Copyright (C) 2014-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `member-moderation` and `nonmember-moderation` rules.""" import unittest from mailman.app.lifecycle import create_list from mailman.interfaces.action import Action from mailman.interfaces.bans import IBanManager from mailman.interfaces.member import MemberRole from mailman.interfaces.usermanager import IUserManager from mailman.rules import moderation from mailman.testing.helpers import ( set_preferred, specialized_message_from_string as mfs) from mailman.testing.layers import ConfigLayer from zope.component import getUtility class TestModeration(unittest.TestCase): """Test the approved handler.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_member_and_nonmember(self): user_manager = getUtility(IUserManager) anne = user_manager.create_address('anne@example.com') user_manager.create_address('bill@example.com') self._mlist.subscribe(anne, MemberRole.member) rule = moderation.NonmemberModeration() msg = mfs("""\ From: anne@example.com Sender: bill@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) # Both Anne and Bill are in the message's senders list. self.assertIn('anne@example.com', msg.senders) self.assertIn('bill@example.com', msg.senders) # The NonmemberModeration rule should *not* hit, because even though # Bill is in the list of senders he is not a member of the mailing # list. Anne is also in the list of senders and she *is* a member, so # she takes precedence. result = rule.check(self._mlist, msg, {}) self.assertFalse(result, 'NonmemberModeration rule should not hit') # After the rule runs, Bill becomes a non-member. bill_member = self._mlist.nonmembers.get_member('bill@example.com') self.assertIsNotNone(bill_member) # Bill is not a member. bill_member = self._mlist.members.get_member('bill@example.com') self.assertIsNone(bill_member) def test_moderation_reason(self): # When a message is moderated, a reason is added to the metadata. user_manager = getUtility(IUserManager) anne = user_manager.create_address('anne@example.com') msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) # Anne is in the message's senders list. self.assertIn('anne@example.com', msg.senders) # Now run the rule. rule = moderation.NonmemberModeration() msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result, 'NonmemberModeration rule should hit') # The reason for moderation should be in the msgdata. reasons = msgdata['moderation_reasons'] self.assertEqual(reasons, ['The message is not from a list member']) # Now make Anne a moderated member... anne_member = self._mlist.subscribe(anne, MemberRole.member) anne_member.moderation_action = Action.hold # ...and run the rule again. rule = moderation.MemberModeration() msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result, 'MemberModeration rule should hit') # The reason for moderation should be in the msgdata. reasons = msgdata['moderation_reasons'] self.assertEqual( reasons, ['The message comes from a moderated member']) def test_these_nonmembers(self): # Test the legacy *_these_nonmembers attributes. user_manager = getUtility(IUserManager) actions = { 'anne@example.com': 'accept', 'bill@example.com': 'hold', 'chris@example.com': 'reject', 'dana@example.com': 'discard', '^anne-.*@example.com': 'accept', '^bill-.*@example.com': 'hold', '^chris-.*@example.com': 'reject', '^dana-.*@example.com': 'discard', } rule = moderation.NonmemberModeration() user_manager = getUtility(IUserManager) for address, action_name in actions.items(): setattr(self._mlist, '{}_these_nonmembers'.format(action_name), [address]) if address.startswith('^'): # It's a pattern, craft a proper address. address = address[1:].replace('.*', 'something') user_manager.create_address(address) msg = mfs("""\ From: {} To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """.format(address)) msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result, 'NonmemberModeration rule should hit') self.assertIn('member_moderation_action', msgdata) self.assertEqual( msgdata['member_moderation_action'], action_name, 'Wrong action for {}: {}'.format(address, action_name)) def test_nonmember_fallback_to_list_defaults(self): # https://gitlab.com/mailman/mailman/issues/189 self._mlist.default_nonmember_action = Action.hold user_manager = getUtility(IUserManager) user_manager.create_address('anne@example.com') rule = moderation.NonmemberModeration() msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) # First, the message should get held. msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['member_moderation_action'], 'hold') # As a side-effect, Anne has been added as a nonmember with a # moderation action that falls back to the list's default. anne = self._mlist.nonmembers.get_member('anne@example.com') self.assertIsNone(anne.moderation_action) # Then the list's default nonmember action is changed. self._mlist.default_nonmember_action = Action.discard msg.replace_header('Message-ID', '') # This time, the message should be discarded. result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata.get('member_moderation_action'), 'discard') def test_member_fallback_to_list_defaults(self): # https://gitlab.com/mailman/mailman/issues/189 self._mlist.default_member_action = Action.accept user_manager = getUtility(IUserManager) anne = user_manager.create_address('anne@example.com') member = self._mlist.subscribe(anne, MemberRole.member) # Anne's moderation rule falls back to the list default. self.assertIsNone(member.moderation_action) rule = moderation.MemberModeration() msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) # First, the message gets accepted. msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata.get('member_moderation_action'), 'accept') # Then the list's default member action is changed. self._mlist.default_member_action = Action.hold msg.replace_header('Message-ID', '') # This time, the message is held. result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata.get('member_moderation_action'), 'hold') def test_linked_address_nonmembermoderation_misses(self): # Anne subscribes to a mailing list as a user with her preferred # address. She also has a secondary linked address, and she uses this # to post to the mailing list. The NonmemberModeration rule misses # because Anne is not a nonmember. user_manager = getUtility(IUserManager) anne = user_manager.create_user('anne@example.com') set_preferred(anne) self._mlist.subscribe(anne, MemberRole.member) anne.link(user_manager.create_address('anne.person@example.com')) rule = moderation.NonmemberModeration() msg = mfs("""\ From: anne.person@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) result = rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_linked_address_membermoderation_hits(self): # Anne subscribes to a mailing list as a user with her preferred # address. She also has a secondary linked address, and she uses this # to post to the mailing list. The MemberModeration rule hits because # Anne is a member. self._mlist.default_member_action = Action.accept user_manager = getUtility(IUserManager) anne = user_manager.create_user('anne@example.com') set_preferred(anne) self._mlist.subscribe(anne, MemberRole.member) anne.link(user_manager.create_address('anne.person@example.com')) rule = moderation.MemberModeration() msg = mfs("""\ From: anne.person@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) result = rule.check(self._mlist, msg, {}) self.assertTrue(result) def test_banned_address_linked_to_user(self): # Anne is subscribed to a mailing list as a user with her preferred # address. She also has a secondary address which is banned and which # she uses to post to the mailing list. Both the MemberModeration and # NonmemberModeration rules miss because the posting address is # banned. user_manager = getUtility(IUserManager) anne = user_manager.create_user('anne@example.com') set_preferred(anne) self._mlist.subscribe(anne, MemberRole.member) anne.link(user_manager.create_address('anne.person@example.com')) IBanManager(self._mlist).ban('anne.person@example.com') msg = mfs("""\ From: anne.person@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) rule = moderation.MemberModeration() result = rule.check(self._mlist, msg, {}) self.assertFalse(result) rule = moderation.NonmemberModeration() result = rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_banned_sender_among_multiple_senders(self): # Two addresses are created, one of which is banned. Even though the # The Nonmember moderation rule misses if any of the banned addresses # appear in the 'senders' headers of the message. user_manager = getUtility(IUserManager) user_manager.create_address('anne@example.com') user_manager.create_address('bart@example.com') IBanManager(self._mlist).ban('bart@example.com') rule = moderation.NonmemberModeration() msg = mfs("""\ From: anne@example.com Sender: bart@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) result = rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_no_senders(self): rule = moderation.NonmemberModeration() # Message without a From msg = mfs("""\ To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) self.assertEqual(msg.senders, []) msgdata = {} # The NonmemberModeration rule should hit. result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result, 'NonmemberModeration rule should hit') self.assertEqual(msgdata, { 'member_moderation_action': Action.hold, 'moderation_reasons': ['No sender was found in the message.'], 'moderation_sender': 'No sender', }) mailman-3.1.1/src/mailman/rules/tests/test_no_senders.py0000664000175000017500000000342113203223435024520 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `no_subject` header rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.email.message import Message from mailman.rules import no_senders from mailman.testing.layers import ConfigLayer class TestNoSender(unittest.TestCase): """Test the no_senders rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') self._rule = no_senders.NoSenders() def test_message_has_no_sender(self): msg = Message() msgdata = {} result = self._rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], ['The message has no valid senders']) self.assertEqual(msgdata['moderation_sender'], 'N/A') def test_message_has_sender(self): msg = Message() msg['From'] = 'anne@example.com' msgdata = {} result = self._rule.check(self._mlist, msg, msgdata) self.assertFalse(result) self.assertEqual(msgdata, {}) mailman-3.1.1/src/mailman/rules/tests/test_dmarc.py0000664000175000017500000004445213203705633023465 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Tests and mocks for DMARC rule.""" import os import threading from contextlib import ExitStack from datetime import timedelta from dns.exception import DNSException from dns.rdatatype import CNAME, TXT from dns.resolver import NXDOMAIN, NoAnswer from http.server import BaseHTTPRequestHandler, HTTPServer from lazr.config import as_timedelta from mailman.app.lifecycle import create_list from mailman.config import config from mailman.interfaces.mailinglist import DMARCMitigateAction from mailman.rules import dmarc from mailman.testing.helpers import ( LogFileMark, configuration, specialized_message_from_string as mfs, wait_for_webservice) from mailman.testing.layers import ConfigLayer from mailman.utilities.datetime import now from pkg_resources import resource_filename from public import public from unittest import TestCase from unittest.mock import patch @public def get_dns_resolver( rtype=TXT, rdata=b'v=DMARC1; p=reject;', rmult=False, cmult=False, cloop=False, cmiss=False): """Create a dns.resolver.Resolver mock. This is used to return a predictable response to a _dmarc query. It returns p=reject for the example.biz domain and raises an exception for other examples. It only implements those classes and attributes used by the dmarc rule. """ class Name: # Mock answer.name. def __init__(self, name='_dmarc.example.biz.'): self.name = name def to_text(self): return self.name class Item: # Mock answer.items. def __init__(self, rdata=rdata, cname='_dmarc.example.com.'): self.strings = [rdata] # For CNAMEs. self.target = Name(cname) class Ans_e: # Mock answer element. def __init__( self, rtype=rtype, rdata=rdata, cname='_dmarc.example.com.', name='_dmarc.example.biz.'): self.rdtype = rtype self.items = [Item(rdata, cname)] self.name = Name(name) class Answer: # Mock answer. def __init__(self): if cloop: self.answer = [ Ans_e( rtype=CNAME, name='_dmarc.example.biz.', cname='_dmarc.example.org.' ), Ans_e( rtype=CNAME, name='_dmarc.example.org.', cname='_dmarc.example.biz.' ), Ans_e( rtype=TXT, name='_dmarc.example.org.', rdata=b'v=DMARC1; p=reject;' ), ] elif cmult: self.answer = [ Ans_e( rtype=CNAME, name='_dmarc.example.biz.', cname='_dmarc.example.net.' ), Ans_e( rtype=CNAME, name='_dmarc.example.net.', cname='_dmarc.example.com.' ), Ans_e( rtype=TXT, name='_dmarc.example.com.', rdata=b'v=DMARC1; p=quarantine;' ), ] elif cmiss: self.answer = [ Ans_e( rtype=CNAME, name='_dmarc.example.biz.', cname='_dmarc.example.net.' ), Ans_e( rtype=TXT, name='_dmarc.example.biz.', rdata=b'v=DMARC1; p=reject;' ), ] elif rmult: self.answer = [Ans_e(), Ans_e(rdata=b'v=DMARC1; p=none;')] else: self.answer = [Ans_e()] class Resolver: # Mock dns.resolver.Resolver class. def query(self, domain, data_type): if data_type != TXT: raise NoAnswer dparts = domain.split('.') if len(dparts) < 3: raise NXDOMAIN if len(dparts) > 3: raise NoAnswer if dparts[0] != '_dmarc': raise NoAnswer if dparts[2] == 'info': raise DNSException('no internet') if dparts[1] != 'example' or dparts[2] != 'biz': raise NXDOMAIN self.response = Answer() return self patcher = patch('dns.resolver.Resolver', Resolver) return patcher @public def use_test_organizational_data(): # Point the organizational URL to our test data. path = resource_filename('mailman.rules.tests.data', 'org_domain.txt') url = 'file:///{}'.format(path) return configuration('dmarc', org_domain_data_url=url) class TestDMARCRules(TestCase): """Test organizational domain determination.""" layer = ConfigLayer def setUp(self): self.resources = ExitStack() self.addCleanup(self.resources.close) # Make sure every test has a clean cache. self.cache = {} self.resources.enter_context( patch('mailman.rules.dmarc.suffix_cache', self.cache)) self.resources.enter_context(use_test_organizational_data()) def test_no_data_for_domain(self): self.assertEqual( dmarc.get_organizational_domain('sub.dom.example.nxtld'), 'example.nxtld') def test_domain_with_wild_card(self): self.assertEqual( dmarc.get_organizational_domain('ssub.sub.foo.kobe.jp'), 'sub.foo.kobe.jp') def test_exception_to_wild_card(self): self.assertEqual( dmarc.get_organizational_domain('ssub.sub.city.kobe.jp'), 'city.kobe.jp') def test_no_at_sign_in_from_address(self): # If there's no @ sign in the From: address, the rule can't hit. mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne To: ant@example.com """) rule = dmarc.DMARCMitigation() with get_dns_resolver(): self.assertFalse(rule.check(mlist, msg, {})) def test_dmarc_dns_exception(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@example.info To: ant@example.com """) mark = LogFileMark('mailman.error') rule = dmarc.DMARCMitigation() with get_dns_resolver(): self.assertFalse(rule.check(mlist, msg, {})) line = mark.readline() self.assertEqual( line[-144:], 'DNSException: Unable to query DMARC policy for ' 'anne@example.info (_dmarc.example.info). ' 'Abstract base class shared by all dnspython exceptions.\n') def test_cname_wrong_txt_name(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@example.biz To: ant@example.com """) rule = dmarc.DMARCMitigation() with get_dns_resolver(cmiss=True): self.assertFalse(rule.check(mlist, msg, {})) def test_domain_with_subdomain_policy(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@example.biz To: ant@example.com """) rule = dmarc.DMARCMitigation() with get_dns_resolver(rdata=b'v=DMARC1; sp=quarantine;'): self.assertFalse(rule.check(mlist, msg, {})) def test_org_domain_with_subdomain_policy(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@sub.domain.example.biz To: ant@example.com """) rule = dmarc.DMARCMitigation() with get_dns_resolver(rdata=b'v=DMARC1; sp=quarantine;'): self.assertTrue(rule.check(mlist, msg, {})) def test_wrong_dmarc_version(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@example.biz To: ant@example.com """) rule = dmarc.DMARCMitigation() with get_dns_resolver(rdata=b'v=DMARC01; p=reject;'): self.assertFalse(rule.check(mlist, msg, {})) def test_multiple_records(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@example.biz To: ant@example.com """) mark = LogFileMark('mailman.error') rule = dmarc.DMARCMitigation() with get_dns_resolver(rmult=True): self.assertTrue(rule.check(mlist, msg, {})) line = mark.readline() self.assertEqual( line[-85:], 'RRset of TXT records for _dmarc.example.biz has 2 ' 'v=DMARC1 entries; testing them all\n') def test_multiple_cnames(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@example.biz To: ant@example.com """) mark = LogFileMark('mailman.vette') rule = dmarc.DMARCMitigation() with get_dns_resolver(cmult=True): self.assertTrue(rule.check(mlist, msg, {})) line = mark.readline() self.assertEqual( line[-128:], 'ant: DMARC lookup for anne@example.biz (_dmarc.example.biz) ' 'found p=quarantine in _dmarc.example.com. = v=DMARC1; ' 'p=quarantine;\n') def test_looping_cnames(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@example.biz To: ant@example.com """) mark = LogFileMark('mailman.vette') rule = dmarc.DMARCMitigation() with get_dns_resolver(cloop=True): self.assertTrue(rule.check(mlist, msg, {})) line = mark.readline() self.assertEqual( line[-120:], 'ant: DMARC lookup for anne@example.biz (_dmarc.example.biz) ' 'found p=reject in _dmarc.example.org. = v=DMARC1; p=reject;\n') def test_no_policy(self): mlist = create_list('ant@example.com') # Use action reject. The rule only hits on reject and discard. mlist.dmarc_mitigate_action = DMARCMitigateAction.reject msg = mfs("""\ From: anne@example.biz To: ant@example.com """) rule = dmarc.DMARCMitigation() with get_dns_resolver(rdata=b'v=DMARC1; pct=100;'): self.assertFalse(rule.check(mlist, msg, {})) def test_parser(self): data_file = resource_filename( 'mailman.rules.tests.data', 'org_domain.txt') dmarc.parse_suffix_list(data_file) # There is no entry for example.biz because that line starts with # whitespace. self.assertNotIn('biz.example', self.cache) # The file had !city.kobe.jp so the flag says there's an exception. self.assertTrue(self.cache['jp.kobe.city']) # The file had *.kobe.jp so there's no exception. self.assertFalse(self.cache['jp.kobe.*']) # New in Python 3.5. try: from http import HTTPStatus except ImportError: class HTTPStatus: FORBIDDEN = 403 NOT_FOUND = 404 OK = 200 # We need a web server to vend non-mailman: urls. class TestableHandler(BaseHTTPRequestHandler): # Be quiet. def log_request(*args, **kws): pass log_error = log_request def do_GET(self): if self.path == '/public_suffix_list.dat': self.send_response(HTTPStatus.OK) self.send_header('Content-Type', 'UTF-8') self.end_headers() self.wfile.write(b'abc') else: self.send_error(HTTPStatus.NOT_FOUND) class HTTPLayer(ConfigLayer): httpd = None @classmethod def setUp(cls): assert cls.httpd is None, 'Layer already set up' cls.httpd = HTTPServer(('localhost', 8180), TestableHandler) cls._thread = threading.Thread(target=cls.httpd.serve_forever) cls._thread.daemon = True cls._thread.start() wait_for_webservice('localhost', 8180) @classmethod def tearDown(cls): assert cls.httpd is not None, 'Layer not set up' cls.httpd.shutdown() cls.httpd.server_close() cls._thread.join() class TestSuffixList(TestCase): layer = HTTPLayer def test_cached_copy_is_good(self): cache_path = os.path.join(config.VAR_DIR, dmarc.LOCAL_FILE_NAME) with open(cache_path, 'w', encoding='utf-8') as fp: print('xyz', end='', file=fp) # The cache expires a day from now. expires = (now() + timedelta(days=1)).timestamp() os.utime(cache_path, (expires, expires)) new_path = dmarc.ensure_current_suffix_list() self.assertEqual(cache_path, new_path) with open(cache_path, 'r', encoding='utf-8') as fp: contents = fp.read() self.assertEqual(contents, 'xyz') self.assertEqual(os.stat(new_path).st_mtime, expires) @configuration( 'dmarc', org_domain_data_url='http://localhost:8180/public_suffix_list.dat') def test_cached_copy_is_expired(self): cache_path = os.path.join(config.VAR_DIR, dmarc.LOCAL_FILE_NAME) with open(cache_path, 'w', encoding='utf-8') as fp: print('xyz', end='', file=fp) # Expire the cache file. That way the current cached file will be # invalid and a new one will be downloaded. expires = (now() - timedelta(days=1)).timestamp() os.utime(cache_path, (expires, expires)) new_path = dmarc.ensure_current_suffix_list() self.assertEqual(cache_path, new_path) with open(cache_path, 'r', encoding='utf-8') as fp: contents = fp.read() self.assertEqual(contents, 'abc') self.assertEqual( os.stat(new_path).st_mtime, (now() + as_timedelta(config.dmarc.cache_lifetime)).timestamp()) @configuration( 'dmarc', org_domain_data_url='http://localhost:8180/public_suffix_list.dat') def test_cached_copy_is_missing(self): cache_path = os.path.join(config.VAR_DIR, dmarc.LOCAL_FILE_NAME) self.assertFalse(os.path.exists(cache_path)) new_path = dmarc.ensure_current_suffix_list() self.assertEqual(cache_path, new_path) with open(cache_path, 'r', encoding='utf-8') as fp: contents = fp.read() self.assertEqual(contents, 'abc') self.assertEqual( os.stat(new_path).st_mtime, (now() + as_timedelta(config.dmarc.cache_lifetime)).timestamp()) @configuration( 'dmarc', org_domain_data_url='http://localhost:8180/public_suffix_list.err') def test_cached_copy_is_missing_download_404s(self): # There's no cached file and we'll get a 404 with the .err file so # we'll have to fall back to our internal copy. cache_path = os.path.join(config.VAR_DIR, dmarc.LOCAL_FILE_NAME) self.assertFalse(os.path.exists(cache_path)) new_path = dmarc.ensure_current_suffix_list() self.assertEqual(cache_path, new_path) with open(cache_path, 'r', encoding='utf-8') as fp: contents = fp.read() # The contents is *not* equal to our dummy test data, but don't tie it # too closely to the in-tree file contents since that might change # when and if we update that. self.assertNotEqual(contents, 'abc') self.assertEqual( os.stat(new_path).st_mtime, (now() + as_timedelta(config.dmarc.cache_lifetime)).timestamp()) @configuration( 'dmarc', org_domain_data_url='http://localhost:8180/public_suffix_list.err') def test_cached_copy_is_expired_download_404s(self): # Because the cached copy is out of date, we try to download the new # version. But that 404s so we end up continuing to use the cached # copy. cache_path = os.path.join(config.VAR_DIR, dmarc.LOCAL_FILE_NAME) with open(cache_path, 'w', encoding='utf-8') as fp: print('xyz', end='', file=fp) # Expire the cache file. That way the current cached file will be # invalid and a new one will be downloaded. expires = (now() - timedelta(days=1)).timestamp() os.utime(cache_path, (expires, expires)) new_path = dmarc.ensure_current_suffix_list() self.assertEqual(cache_path, new_path) with open(cache_path, 'r', encoding='utf-8') as fp: contents = fp.read() # The contents are from the cached file. self.assertEqual(contents, 'xyz') # The cached file timestamp doesn't change. self.assertEqual(os.stat(new_path).st_mtime, expires) mailman-3.1.1/src/mailman/rules/tests/test_news_moderation.py0000664000175000017500000000346313203223435025564 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `news_moderation` rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.interfaces.nntp import NewsgroupModeration from mailman.rules import news_moderation from mailman.testing.helpers import specialized_message_from_string as mfs from mailman.testing.layers import ConfigLayer class TestModeratedNewsgroup(unittest.TestCase): """Test the news_moderation rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_news_moderation_returns_reason(self): # Ensure news_moderation rule returns a reason. msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Subject Message-ID: A message body. """) rule = news_moderation.ModeratedNewsgroup() self._mlist.newsgroup_moderation = NewsgroupModeration.moderated msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], ['Post to a moderated newsgroup gateway']) mailman-3.1.1/src/mailman/rules/tests/__init__.py0000664000175000017500000000000012632220112023041 0ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/tests/test_implicit_dest.py0000664000175000017500000000324413203223435025215 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `implicit_dest` rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.rules import implicit_dest from mailman.testing.helpers import specialized_message_from_string as mfs from mailman.testing.layers import ConfigLayer class TestImplicitDestination(unittest.TestCase): """Test the implicit_dest rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_implicit_dest_returns_reason(self): # Ensure implicit_dest rule returns a reason. msg = mfs("""\ From: anne@example.com To: bogus@example.com Subject: A Subject Message-ID: A message body. """) rule = implicit_dest.ImplicitDestination() msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], ['Message has implicit destination']) mailman-3.1.1/src/mailman/rules/tests/test_banned_address.py0000664000175000017500000001120313203223435025312 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `banned-address` rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.interfaces.bans import IBanManager from mailman.interfaces.usermanager import IUserManager from mailman.rules import banned_address from mailman.testing.helpers import ( set_preferred, specialized_message_from_string as mfs) from mailman.testing.layers import ConfigLayer from zope.component import getUtility class TestBannedAddress(unittest.TestCase): """Test the banned-address rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_no_banned_sender(self): # Simple case where the sender is not banned. user_manager = getUtility(IUserManager) anne = user_manager.create_user('anne@example.com') set_preferred(anne) msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) rule = banned_address.BannedAddress() result = rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_simple_banned_sender(self): # Simple case where the sender is banned. user_manager = getUtility(IUserManager) anne = user_manager.create_user('anne@example.com') set_preferred(anne) IBanManager(self._mlist).ban('anne@example.com') msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) rule = banned_address.BannedAddress() result = rule.check(self._mlist, msg, {}) self.assertTrue(result) def test_rule_returns_reason(self): # Ensure a reason is returned. user_manager = getUtility(IUserManager) anne = user_manager.create_user('anne@example.com') set_preferred(anne) IBanManager(self._mlist).ban('anne@example.com') msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) rule = banned_address.BannedAddress() msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual( msgdata['moderation_reasons'], [('Message sender {} is banned from this list', 'anne@example.com')]) def test_banned_address_linked_to_user(self): # Anne is subscribed to a mailing list as a user with her preferred # address. She also has a secondary address which is banned and which # she uses to post to the mailing list. The rule matches because the # posting address is banned. user_manager = getUtility(IUserManager) anne = user_manager.create_user('anne@example.com') set_preferred(anne) anne.link(user_manager.create_address('anne.person@example.com')) IBanManager(self._mlist).ban('anne.person@example.com') msg = mfs("""\ From: anne.person@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) rule = banned_address.BannedAddress() result = rule.check(self._mlist, msg, {}) self.assertTrue(result) def test_banned_sender_among_multiple_senders(self): # Two addresses are created, one of which is banned. The rule matches # because all senders are checked. user_manager = getUtility(IUserManager) user_manager.create_address('anne@example.com') user_manager.create_address('bart@example.com') IBanManager(self._mlist).ban('bart@example.com') msg = mfs("""\ From: anne@example.com Sender: bart@example.com To: test@example.com Subject: A test message Message-ID: MIME-Version: 1.0 A message body. """) rule = banned_address.BannedAddress() result = rule.check(self._mlist, msg, {}) self.assertTrue(result) mailman-3.1.1/src/mailman/rules/tests/test_max_size.py0000664000175000017500000000341013203223435024176 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `max_size` rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.rules import max_size from mailman.testing.helpers import specialized_message_from_string as mfs from mailman.testing.layers import ConfigLayer class TestMaximumSize(unittest.TestCase): """Test the max_size rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_max_size_returns_reason(self): # Ensure max_size rule returns a reason. msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Subject Message-ID: A message body. """) rule = max_size.MaximumSize() self._mlist.max_message_size = 1 # Fake the size. msg.original_size = 2048 msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], [('The message is larger than the {} KB maximum size', 1)]) mailman-3.1.1/src/mailman/rules/tests/test_emergency.py0000664000175000017500000000325313203223435024342 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `emergency` rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.rules import emergency from mailman.testing.helpers import specialized_message_from_string as mfs from mailman.testing.layers import ConfigLayer class TestEmergency(unittest.TestCase): """Test the emergency rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_emergency_returns_reason(self): # Ensure emergency rule returns a reason. msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Subject Message-ID: A message body. """) rule = emergency.Emergency() self._mlist.emergency = True msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], ['Emergency moderation is in effect for this list']) mailman-3.1.1/src/mailman/rules/tests/test_no_subject.py0000664000175000017500000000363713203223435024525 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `no_subject` header rule.""" import unittest from email.header import Header from mailman.app.lifecycle import create_list from mailman.email.message import Message from mailman.rules import no_subject from mailman.testing.layers import ConfigLayer class TestNoSubject(unittest.TestCase): """Test the no_subject rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') self._rule = no_subject.NoSubject() def test_header_instance_empty(self): msg = Message() msg['Subject'] = Header('') result = self._rule.check(self._mlist, msg, {}) self.assertTrue(result) def test_header_instance_not_empty(self): msg = Message() msg['Subject'] = Header('Test subject') result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_no_subject_returns_reason(self): msg = Message() msg['Subject'] = Header('') msgdata = {} result = self._rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], ['Message has no subject']) mailman-3.1.1/src/mailman/rules/tests/test_approved.py0000664000175000017500000004573413066532160024223 0ustar maxkingmaxking00000000000000# Copyright (C) 2012-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `approved` handler.""" import os import unittest from mailman.app.lifecycle import create_list from mailman.config import config from mailman.rules import approved from mailman.testing.helpers import ( configuration, specialized_message_from_string as mfs) from mailman.testing.layers import ConfigLayer class TestApproved(unittest.TestCase): """Test the approved handler.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') self._mlist.moderator_password = config.password_context.encrypt( 'super secret') self._rule = approved.Approved() self._msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Message with non-ascii body Message-ID: MIME-Version: 1.0 A message body. """) def test_approved_header(self): self._msg['Approved'] = 'super secret' result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) def test_approve_header(self): self._msg['Approve'] = 'super secret' result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) def test_x_approved_header(self): self._msg['X-Approved'] = 'super secret' result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) def test_x_approve_header(self): self._msg['X-Approve'] = 'super secret' result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) def test_approved_header_wrong_password(self): self._msg['Approved'] = 'not the password' result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) def test_approve_header_wrong_password(self): self._msg['Approve'] = 'not the password' result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) def test_x_approved_header_wrong_password(self): self._msg['X-Approved'] = 'not the password' result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) def test_x_approve_header_wrong_password(self): self._msg['X-Approve'] = 'not the password' result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) def test_removes_approved_header(self): self._msg['Approved'] = 'super secret' self._rule.check(self._mlist, self._msg, {}) self.assertEqual(self._msg['approved'], None) def test_removes_approve_header(self): self._msg['Approve'] = 'super secret' self._rule.check(self._mlist, self._msg, {}) self.assertEqual(self._msg['approve'], None) def test_removes_x_approved_header(self): self._msg['X-Approved'] = 'super secret' self._rule.check(self._mlist, self._msg, {}) self.assertEqual(self._msg['x-approved'], None) def test_removes_x_approve_header(self): self._msg['X-Approve'] = 'super secret' self._rule.check(self._mlist, self._msg, {}) self.assertEqual(self._msg['x-approve'], None) def test_removes_approved_header_wrong_password(self): self._msg['Approved'] = 'not the password' self._rule.check(self._mlist, self._msg, {}) self.assertEqual(self._msg['approved'], None) def test_removes_approve_header_wrong_password(self): self._msg['Approve'] = 'not the password' self._rule.check(self._mlist, self._msg, {}) self.assertEqual(self._msg['approve'], None) def test_removes_x_approved_header_wrong_password(self): self._msg['X-Approved'] = 'not the password' self._rule.check(self._mlist, self._msg, {}) self.assertEqual(self._msg['x-approved'], None) def test_removes_x_approve_header_wrong_password(self): self._msg['X-Approve'] = 'not the password' self._rule.check(self._mlist, self._msg, {}) self.assertEqual(self._msg['x-approve'], None) def test_no_list_password(self): self._mlist.moderator_password = None self._msg['Approved'] = 'super secret' result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) class TestApprovedPseudoHeader(unittest.TestCase): """Test the approved handler.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') self._mlist.moderator_password = config.password_context.encrypt( 'super secret') self._rule = approved.Approved() self._msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Message with non-ascii body Message-ID: MIME-Version: 1.0 """) def test_approved_pseudo_header(self): self._msg.set_payload("""\ Approved: super secret """) result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) def test_approve_pseudo_header(self): self._msg.set_payload("""\ Approve: super secret """) result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) def test_x_approved_pseudo_header(self): self._msg.set_payload("""\ X-Approved: super secret """) result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) def test_x_approve_pseudo_header(self): self._msg.set_payload("""\ X-Approve: super secret """) result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) def test_approved_pseudo_header_wrong_password(self): self._msg.set_payload("""\ Approved: not the password """) result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) def test_approve_pseudo_header_wrong_password(self): self._msg.set_payload("""\ Approve: not the password """) result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) def test_x_approved_pseudo_header_wrong_password(self): self._msg.set_payload("""\ X-Approved: not the password """) result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) def test_x_approve_pseudo_header_wrong_password(self): self._msg.set_payload("""\ X-Approve: not the password """) result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) def test_removes_approved_pseudo_header(self): self._msg.set_payload("""\ Approved: super secret """) self._rule.check(self._mlist, self._msg, {}) self.assertFalse('Approved' in self._msg.get_payload()) def test_removes_approve_pseudo_header(self): self._msg.set_payload("""\ Approve: super secret """) self._rule.check(self._mlist, self._msg, {}) self.assertFalse('Approve' in self._msg.get_payload()) def test_removes_x_approved_pseudo_header(self): self._msg.set_payload("""\ X-Approved: super secret """) self._rule.check(self._mlist, self._msg, {}) self.assertFalse('X-Approved' in self._msg.get_payload()) def test_removes_x_approve_pseudo_header(self): self._msg.set_payload("""\ X-Approve: super secret """) self._rule.check(self._mlist, self._msg, {}) self.assertFalse('X-Approve' in self._msg.get_payload()) def test_removes_approved_pseudo_header_wrong_password(self): self._msg.set_payload("""\ Approved: not the password """) self._rule.check(self._mlist, self._msg, {}) self.assertFalse('Approved' in self._msg.get_payload()) def test_removes_approve_pseudo_header_wrong_password(self): self._msg.set_payload("""\ Approve: not the password """) self._rule.check(self._mlist, self._msg, {}) self.assertFalse('Approve' in self._msg.get_payload()) def test_removes_x_approved_pseudo_header_wrong_password(self): self._msg.set_payload("""\ X-Approved: not the password """) self._rule.check(self._mlist, self._msg, {}) self.assertFalse('X-Approved' in self._msg.get_payload()) def test_removes_x_approve_pseudo_header_wrong_password(self): self._msg.set_payload("""\ X-Approve: not the password """) self._rule.check(self._mlist, self._msg, {}) self.assertFalse('X-Approve' in self._msg.get_payload()) class TestApprovedPseudoHeaderMIME(unittest.TestCase): """Test the approved handler.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') self._mlist.moderator_password = config.password_context.encrypt( 'super secret') self._rule = approved.Approved() self._msg_text_template = """\ From: anne@example.com To: test@example.com Subject: A Message with non-ascii body Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="AAA" --AAA Content-Type: application/x-ignore {0}: not the password The above line will be ignored. --AAA Content-Type: text/plain {0}: {1} An important message. """ def test_approved_pseudo_header_mime(self): msg = mfs(self._msg_text_template.format('Approved', 'super secret')) result = self._rule.check(self._mlist, msg, {}) self.assertTrue(result) def test_approve_pseudo_header_mime(self): msg = mfs(self._msg_text_template.format('Approve', 'super secret')) result = self._rule.check(self._mlist, msg, {}) self.assertTrue(result) def test_x_approved_pseudo_header_mime(self): msg = mfs(self._msg_text_template.format('X-Approved', 'super secret')) result = self._rule.check(self._mlist, msg, {}) self.assertTrue(result) def test_x_approve_pseudo_header_mime(self): msg = mfs(self._msg_text_template.format('X-Approve', 'super secret')) result = self._rule.check(self._mlist, msg, {}) self.assertTrue(result) def test_approved_pseudo_header_wrong_password_mime(self): msg = mfs(self._msg_text_template.format('Approved', 'not password')) result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_approve_pseudo_header_wrong_password_mime(self): msg = mfs(self._msg_text_template.format('Approve', 'not password')) result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_x_approved_pseudo_header_wrong_password_mime(self): msg = mfs(self._msg_text_template.format('X-Approved', 'not password')) result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_x_approve_pseudo_header_wrong_password_mime(self): msg = mfs(self._msg_text_template.format('X-Approve', 'not password')) result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_removes_approved_pseudo_header_mime(self): msg = mfs(self._msg_text_template.format('Approved', 'super secret')) self._rule.check(self._mlist, msg, {}) self.assertFalse('Approved' in msg.get_payload(1).get_payload()) def test_removes_approve_pseudo_header_mime(self): msg = mfs(self._msg_text_template.format('Approve', 'super secret')) self._rule.check(self._mlist, msg, {}) self.assertFalse('Approve' in msg.get_payload(1).get_payload()) def test_removes_x_approved_pseudo_header_mime(self): msg = mfs(self._msg_text_template.format('X-Approved', 'super secret')) self._rule.check(self._mlist, msg, {}) self.assertFalse('X-Approved' in msg.get_payload(1).get_payload()) def test_removes_x_approve_pseudo_header_mime(self): msg = mfs(self._msg_text_template.format('X-Approve', 'super secret')) self._rule.check(self._mlist, msg, {}) self.assertFalse('X-Approve' in msg.get_payload(1).get_payload()) def test_removes_approved_pseudo_header_wrong_password_mime(self): msg = mfs(self._msg_text_template.format('Approved', 'not password')) self._rule.check(self._mlist, msg, {}) self.assertFalse('Approved' in msg.get_payload(1).get_payload()) def test_removes_approve_pseudo_header_wrong_password_mime(self): msg = mfs(self._msg_text_template.format('Approve', 'not password')) self._rule.check(self._mlist, msg, {}) self.assertFalse('Approve' in msg.get_payload(1).get_payload()) def test_removes_x_approved_pseudo_header_wrong_password_mime(self): msg = mfs(self._msg_text_template.format('X-Approved', 'not password')) self._rule.check(self._mlist, msg, {}) self.assertFalse('X-Approved' in msg.get_payload(1).get_payload()) def test_removes_x_approve_pseudo_header_wrong_password_mime(self): msg = mfs(self._msg_text_template.format('X-Approve', 'not password')) self._rule.check(self._mlist, msg, {}) self.assertFalse('X-Approve' in msg.get_payload(1).get_payload()) class TestApprovedNonASCII(unittest.TestCase): """Test the approved handler with non-ascii messages.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') self._mlist.moderator_password = config.password_context.encrypt( 'super secret') self._rule = approved.Approved() def test_nonascii_body_missing_header(self): # When the message body contains non-ascii, the rule should not throw # unicode errors. LP: #949924. msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Message with non-ascii body Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable This is a message body with a non-ascii character =E4 """) result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) def test_unknown_charset(self): # When the charset is unknown, the rule should not crash. GL: #203 msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Message with non-ascii body Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=unknown-8bit Content-Disposition: inline Content-Transfer-Encoding: quoted-printable This is a message body with a non-ascii character =E4 """) result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) class TestPasswordHashMigration(unittest.TestCase): """Test that password hashing migrations work.""" # http://packages.python.org/passlib/lib/passlib.context-tutorial.html#integrating-hash-migration layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') # The default testing hash algorithm is "roundup_plaintext" which # yields hashed passwords of the form: {plaintext}abc # # Migration is automatically supported when a more modern password # hash is chosen after the original password is set. As long as the # old password still validates, the migration happens automatically. self._mlist.moderator_password = config.password_context.encrypt( 'super secret') self._rule = approved.Approved() self._msg = mfs("""\ From: anne@example.com To: test@example.com Subject: A Message with non-ascii body Message-ID: MIME-Version: 1.0 A message body. """) def test_valid_password_migrates(self): # Now that the moderator password is set, change the default password # hashing algorithm. When the old password is validated, it will be # automatically migrated to the new hash. self.assertEqual(self._mlist.moderator_password, '{plaintext}super secret') config_file = os.path.join(config.VAR_DIR, 'passlib.config') # XXX passlib seems to choose the default hashing scheme even if it is # deprecated. The default scheme is either specified explicitly, or # is the first in this list. This seems like a bug. with open(config_file, 'w') as fp: print("""\ [passlib] schemes = roundup_plaintext, plaintext default = plaintext deprecated = roundup_plaintext """, file=fp) with configuration('passwords', configuration=config_file): self._msg['Approved'] = 'super secret' result = self._rule.check(self._mlist, self._msg, {}) self.assertTrue(result) self.assertEqual(self._mlist.moderator_password, 'super secret') def test_invalid_password_does_not_migrate(self): # Now that the moderator password is set, change the default password # hashing algorithm. When the old password is invalid, it will not be # automatically migrated to the new hash. self.assertEqual(self._mlist.moderator_password, '{plaintext}super secret') config_file = os.path.join(config.VAR_DIR, 'passlib.config') # XXX passlib seems to choose the default hashing scheme even if it is # deprecated. The default scheme is either specified explicitly, or # is the first in this list. This seems like a bug. with open(config_file, 'w') as fp: print("""\ [passlib] schemes = roundup_plaintext, plaintext default = plaintext deprecated = roundup_plaintext """, file=fp) with configuration('passwords', configuration=config_file): self._msg['Approved'] = 'not the password' result = self._rule.check(self._mlist, self._msg, {}) self.assertFalse(result) self.assertEqual(self._mlist.moderator_password, '{plaintext}super secret') class TestApprovedNoTextPlainPart(unittest.TestCase): """Test the approved handler with HTML-only messages.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') self._rule = approved.Approved() def test_no_text_plain_part(self): # When the message body only contains HTML, the rule should not throw # AttributeError: 'NoneType' object has no attribute 'get_payload' # LP: #1158721 msg = mfs("""\ From: anne@example.com To: test@example.com Subject: HTML only email Message-ID: MIME-Version: 1.0 Content-Type: text/html; charset="Windows-1251" Content-Transfer-Encoding: 7bit

This message contains only HTML, no plain/text part

""") result = self._rule.check(self._mlist, msg, {}) self.assertFalse(result) mailman-3.1.1/src/mailman/rules/tests/test_administrivia.py0000664000175000017500000000322713203223435025230 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Test the `administrivia` rule.""" import unittest from mailman.app.lifecycle import create_list from mailman.rules import administrivia from mailman.testing.helpers import specialized_message_from_string as mfs from mailman.testing.layers import ConfigLayer class TestAdministrivia(unittest.TestCase): """Test the administrivia rule.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') def test_administrivia_returns_reason(self): # Ensure administrivia rule returns a reason. msg = mfs("""\ From: anne@example.com To: test@example.com Subject: unsubscribe Message-ID: A message body. """) rule = administrivia.Administrivia() msgdata = {} result = rule.check(self._mlist, msg, msgdata) self.assertTrue(result) self.assertEqual(msgdata['moderation_reasons'], ['Message contains administrivia']) mailman-3.1.1/src/mailman/rules/__init__.py0000664000175000017500000000000012632220112021677 0ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/news_moderation.py0000664000175000017500000000326713203223435023365 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The news moderation rule.""" from mailman.core.i18n import _ from mailman.interfaces.nntp import NewsgroupModeration from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class ModeratedNewsgroup: """The news moderation rule.""" name = 'news-moderation' description = _( """Match all messages posted to a mailing list that gateways to a moderated newsgroup. """) record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" if mlist.newsgroup_moderation is NewsgroupModeration.moderated: msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('Post to a moderated newsgroup gateway')) return True return False mailman-3.1.1/src/mailman/rules/administrivia.py0000664000175000017500000000727313203223435023034 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The administrivia rule.""" from email.iterators import typed_subpart_iterator from mailman.config import config from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer # The list of email commands we search for in the Subject header and payload. # We probably should get this information from the actual implemented # commands. EMAIL_COMMANDS = { # keyword: (minimum #args, maximum #args) 'confirm': (1, 1), 'help': (0, 0), 'info': (0, 0), 'lists': (0, 0), 'options': (0, 0), 'password': (2, 2), 'remove': (0, 0), 'set': (3, 3), 'subscribe': (0, 3), 'unsubscribe': (0, 1), 'who': (0, 2), } @public @implementer(IRule) class Administrivia: """The administrivia rule.""" name = 'administrivia' description = _('Catch mis-addressed email commands.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" # The list must have the administrivia check enabled. if not mlist.administrivia: return False # First check the Subject text. lines_to_check = [] subject = str(msg.get('subject', '')) if subject != '': lines_to_check.append(subject) # Search only the first text/plain subpart of the message. There's # really no good way to find email commands in any other content type. for part in typed_subpart_iterator(msg, 'text', 'plain'): payload = part.get_payload() lines = payload.splitlines() # Count lines without using enumerate() because blank lines in the # payload don't count against the maximum examined. lineno = 0 for line in lines: line = line.strip() if len(line) == 0: continue lineno += 1 if lineno > int(config.mailman.email_commands_max_lines): break lines_to_check.append(line) # Only look at the first text/plain part. break # For each line we're checking, split the line into words. Then see # if it looks like a command with the min-to-max number of arguments. for line in lines_to_check: words = [word.lower() for word in line.split()] if words[0] not in EMAIL_COMMANDS: # This is not an administrivia command. continue minargs, maxargs = EMAIL_COMMANDS[words[0]] if minargs <= len(words) - 1 <= maxargs: msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('Message contains administrivia')) return True return False mailman-3.1.1/src/mailman/rules/emergency.py0000664000175000017500000000321313203223435022135 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The emergency hold rule.""" from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class Emergency: """The emergency hold rule.""" name = 'emergency' description = _( """The mailing list is in emergency hold and this message was not pre-approved by the list administrator. """) record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" if mlist.emergency and not msgdata.get('moderator_approved'): msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('Emergency moderation is in effect for this list')) return True return False mailman-3.1.1/src/mailman/rules/max_recipients.py0000664000175000017500000000367713203223435023207 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The maximum number of recipients rule.""" from email.utils import getaddresses from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer @public @implementer(IRule) class MaximumRecipients: """The maximum number of recipients rule.""" name = 'max-recipients' description = _('Catch messages with too many explicit recipients.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" # Zero means any number of recipients are allowed. if mlist.max_num_recipients == 0: return False # Figure out how many recipients there are recipients = getaddresses(msg.get_all('to', []) + msg.get_all('cc', [])) if len(recipients) >= mlist.max_num_recipients: msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( (_('Message has more than {} recipients'), mlist.max_num_recipients)) return True return False mailman-3.1.1/src/mailman/rules/moderation.py0000664000175000017500000001673313203223435022333 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Membership related rules.""" import re from mailman.core.i18n import _ from mailman.interfaces.action import Action from mailman.interfaces.bans import IBanManager from mailman.interfaces.member import MemberRole from mailman.interfaces.rules import IRule from mailman.interfaces.usermanager import IUserManager from public import public from zope.component import getUtility from zope.interface import implementer def _find_sender_member(mlist, msg): # For every sender email in the message, try to find a member associated # with that email. # # First, check the sender email directly. If it's a member, we're done. # # Next, check to see if the sender email is linked to an existing user, # and if so, check to see if any of the addresses linked to that user is a # member. user_manager = getUtility(IUserManager) for sender in msg.senders: member = mlist.members.get_member(sender) if member is not None: return member user = user_manager.get_user(sender) if user is not None: for address in user.addresses: member = mlist.members.get_member(address.email) if member is not None: return member return None @public @implementer(IRule) class MemberModeration: """The member moderation rule.""" name = 'member-moderation' description = _('Match messages sent by moderated members.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" # The MemberModeration rule misses unconditionally if any of the # senders are banned. ban_manager = IBanManager(mlist) for sender in msg.senders: if ban_manager.is_banned(sender): return False member = _find_sender_member(mlist, msg) if member is None: return False action = (mlist.default_member_action if member.moderation_action is None else member.moderation_action) if action is Action.defer: # The regular moderation rules apply. return False elif action is not None: # We must stringify the moderation action so that it can be # stored in the pending request table. msgdata['member_moderation_action'] = action.name msgdata['moderation_sender'] = sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('The message comes from a moderated member')) return True # The sender is not a member so this rule does not match. return False def _record_action(msgdata, action, sender, reason): msgdata['member_moderation_action'] = action msgdata['moderation_sender'] = sender msgdata.setdefault('moderation_reasons', []).append(reason) @public @implementer(IRule) class NonmemberModeration: """The nonmember moderation rule.""" name = 'nonmember-moderation' description = _('Match messages sent by nonmembers.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" ban_manager = IBanManager(mlist) user_manager = getUtility(IUserManager) # The NonmemberModeration rule misses unconditionally if any of the # senders are banned. for sender in msg.senders: if ban_manager.is_banned(sender): return False if len(msg.senders) == 0: with _.defer_translation(): # This will be translated at the point of use. reason = _('No sender was found in the message.') _record_action( msgdata, mlist.default_nonmember_action, 'No sender', reason) return True # Every sender email must be a member or nonmember directly. If it is # neither, make the email a nonmembers. for sender in msg.senders: if (mlist.members.get_member(sender) is None and mlist.nonmembers.get_member(sender) is None): # noqa # The email must already be registered, since this happens in # the incoming runner itself. address = user_manager.get_address(sender) assert address is not None, ( 'Posting address is not registered: {}'.format(sender)) mlist.subscribe(address, MemberRole.nonmember) # Check to see if any of the sender emails is already a member. If # so, then this rule misses. member = _find_sender_member(mlist, msg) if member is not None: return False # Do nonmember moderation check. for sender in msg.senders: nonmember = mlist.nonmembers.get_member(sender) assert nonmember is not None, ( "sender didn't get subscribed as a nonmember".format(sender)) # Check the '*_these_nonmembers' properties first. XXX These are # legacy attributes from MM2.1; their database type is 'pickle' and # they should eventually get replaced. for action_name in ('accept', 'hold', 'reject', 'discard'): legacy_attribute_name = '{}_these_nonmembers'.format( action_name) checklist = getattr(mlist, legacy_attribute_name) for addr in checklist: if ((addr.startswith('^') and re.match(addr, sender)) or addr == sender): # noqa: W503 with _.defer_translation(): # This will be translated at the point of use. reason = ( _('The sender is in the nonmember {} list'), action_name) _record_action(msgdata, action_name, sender, reason) return True action = (mlist.default_nonmember_action if nonmember.moderation_action is None else nonmember.moderation_action) if action is Action.defer: # The regular moderation rules apply. return False elif action is not None: # We must stringify the moderation action so that it can be # stored in the pending request table. with _.defer_translation(): # This will be translated at the point of use. reason = _('The message is not from a list member') _record_action(msgdata, action.name, sender, reason) return True # The sender must be a member, so this rule does not match. return False mailman-3.1.1/src/mailman/rules/docs/0000775000175000017500000000000013204154702020537 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/docs/dmarc-mitigation.rst0000664000175000017500000001061313203705633024526 0ustar maxkingmaxking00000000000000================ DMARC mitigation ================ This rule only matches in order to jump to the moderation chain to reject or discard the message. The rule looks at the list's ``dmarc_mitigate_action`` and if it is other than ``no_mitigation``, it checks the domain of the ``From:`` address for a DMARC policy. Depending on various settings, reject or discard the message, or just flag it for the dmarc handler to apply DMARC mitigations to the message. >>> mlist = create_list('ant@example.com') >>> rule = config.rules['dmarc-mitigation'] >>> print(rule.name) dmarc-mitigation First we set up a mock to return predictable responses to DNS lookups. This returns ``p=reject`` for the ``example.biz`` domain and not for any others. >>> from mailman.rules.tests.test_dmarc import get_dns_resolver >>> ignore = cleanups.enter_context(get_dns_resolver()) Use test data for the organizational domain suffixes. >>> from mailman.rules.tests.test_dmarc import use_test_organizational_data >>> cleanups.enter_context(use_test_organizational_data()) A message ``From:`` a domain without a DMARC policy does not set any flags. >>> from mailman.interfaces.mailinglist import DMARCMitigateAction >>> mlist.dmarc_mitigate_action = DMARCMitigateAction.munge_from >>> msg = message_from_string("""\ ... From: aperson@example.org ... To: ant@example.com ... Subject: A posted message ... ... """) >>> msgdata = {} >>> rule.check(mlist, msg, msgdata) False >>> msgdata {} Even if the ``From:`` domain publishes ``p=reject``, no flags are set if the list's action is ``no_mitigation``. >>> mlist.dmarc_mitigate_action = DMARCMitigateAction.no_mitigation >>> msg = message_from_string("""\ ... From: aperson@example.biz ... To: ant@example.com ... Subject: A posted message ... ... """) >>> msgdata = {} >>> rule.check(mlist, msg, msgdata) False >>> msgdata {} With a mitigation strategy chosen, the message is flagged. >>> mlist.dmarc_mitigate_action = DMARCMitigateAction.munge_from >>> msg = message_from_string("""\ ... From: aperson@example.biz ... To: ant@example.com ... Subject: A posted message ... ... """) >>> msgdata = {} >>> rule.check(mlist, msg, msgdata) False >>> msgdata {'dmarc': True} Subdomains which don't have a policy will check the organizational domain. >>> msg = message_from_string("""\ ... From: aperson@sub.domain.example.biz ... To: ant@example.com ... Subject: A posted message ... ... """) >>> msgdata = {} >>> rule.check(mlist, msg, msgdata) False >>> msgdata {'dmarc': True} The list's action can also be set to immediately discard or reject the message. >>> mlist.dmarc_mitigate_action = DMARCMitigateAction.discard >>> msg = message_from_string("""\ ... From: aperson@example.biz ... To: ant@example.com ... Subject: A posted message ... Message-ID: ... ... """) >>> msgdata = {} >>> rule.check(mlist, msg, msgdata) True >>> dump_msgdata(msgdata) dmarc : True dmarc_action : discard moderation_reasons: ['DMARC moderation'] moderation_sender : aperson@example.biz We can reject the message with a default reason. >>> mlist.dmarc_mitigate_action = DMARCMitigateAction.reject >>> msg = message_from_string("""\ ... From: aperson@example.biz ... To: ant@example.com ... Subject: A posted message ... Message-ID: ... ... """) >>> msgdata = {} >>> rule.check(mlist, msg, msgdata) True >>> dump_msgdata(msgdata) dmarc : True dmarc_action : reject moderation_reasons: ['You are not allowed to post to this mailing list... moderation_sender : aperson@example.biz And, we can reject with a custom message. >>> mlist.dmarc_moderation_notice = 'A silly reason' >>> msg = message_from_string("""\ ... From: aperson@example.biz ... To: ant@example.com ... Subject: A posted message ... Message-ID: ... ... """) >>> msgdata = {} >>> rule.check(mlist, msg, msgdata) True >>> dump_msgdata(msgdata) dmarc : True dmarc_action : reject moderation_reasons: ['A silly reason'] moderation_sender : aperson@example.biz mailman-3.1.1/src/mailman/rules/docs/emergency.rst0000664000175000017500000000174112632220112023243 0ustar maxkingmaxking00000000000000========= Emergency ========= When the mailing list has its emergency flag set, all messages posted to the list are held for moderator approval. >>> mlist = create_list('test@example.com') >>> rule = config.rules['emergency'] >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: test@example.com ... Subject: My first post ... Message-ID: ... ... An important message. ... """) By default, the mailing list does not have its emergency flag set. >>> mlist.emergency False >>> rule.check(mlist, msg, {}) False The emergency rule matches if the flag is set on the mailing list. >>> mlist.emergency = True >>> rule.check(mlist, msg, {}) True However, if the message metadata has a ``moderator_approved`` key set, then even if the mailing list has its emergency flag set, the message still goes through to the membership. >>> rule.check(mlist, msg, dict(moderator_approved=True)) False mailman-3.1.1/src/mailman/rules/docs/no-subject.rst0000664000175000017500000000151312632220112023333 0ustar maxkingmaxking00000000000000================= No Subject header ================= This rule matches if the message has no ``Subject:`` header, or if the header is the empty string when stripped. >>> mlist = create_list('_xtest@example.com') >>> rule = config.rules['no-subject'] >>> print(rule.name) no-subject A message with a non-empty subject does not match the rule. >>> msg = message_from_string("""\ ... From: aperson@example.org ... To: _xtest@example.com ... Subject: A posted message ... ... """) >>> rule.check(mlist, msg, {}) False Delete the ``Subject:`` header and the rule matches. >>> del msg['subject'] >>> rule.check(mlist, msg, {}) True Even a ``Subject:`` header with only whitespace still matches the rule. >>> msg['Subject'] = ' ' >>> rule.check(mlist, msg, {}) True mailman-3.1.1/src/mailman/rules/docs/__init__.py0000664000175000017500000000000012632220112022627 0ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rules/docs/recipients.rst0000664000175000017500000000222012632220112023423 0ustar maxkingmaxking00000000000000============================ Maximum number of recipients ============================ This rule matches when there are more than the maximum allowed number of explicit recipients addressed by the message. >>> mlist = create_list('_xtest@example.com') >>> rule = config.rules['max-recipients'] >>> print(rule.name) max-recipients In this case, we'll create a message with five recipients. These include all addresses in the ``To:`` and ``CC:`` headers. >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: _xtest@example.com, bperson@example.com ... Cc: cperson@example.com ... Cc: dperson@example.com (Dan Person) ... To: Elly Q. Person ... ... Hey folks! ... """) For backward compatibility, the message must have fewer than the maximum number of explicit recipients. >>> mlist.max_num_recipients = 5 >>> rule.check(mlist, msg, {}) True >>> mlist.max_num_recipients = 6 >>> rule.check(mlist, msg, {}) False Zero means any number of recipients are allowed. >>> mlist.max_num_recipients = 0 >>> rule.check(mlist, msg, {}) False mailman-3.1.1/src/mailman/rules/docs/rules.rst0000664000175000017500000000357713203223435022436 0ustar maxkingmaxking00000000000000===== Rules ===== Rules are applied to each message as part of a rule chain. Individual rules simply return a boolean specifying whether the rule matches or not. Chain links determine what happens when a rule matches. All rules ========= Rules are maintained in the configuration object as a dictionary mapping rule names to rule objects. >>> from zope.interface.verify import verifyObject >>> from mailman.interfaces.rules import IRule >>> for rule_name in sorted(config.rules): ... rule = config.rules[rule_name] ... print(rule_name, verifyObject(IRule, rule)) administrivia True any True approved True banned-address True dmarc-mitigation True emergency True implicit-dest True loop True max-recipients True max-size True member-moderation True news-moderation True no-senders True no-subject True nonmember-moderation True suspicious-header True truth True You can get a rule by name. >>> rule = config.rules['emergency'] >>> verifyObject(IRule, rule) True Rule checks =========== Individual rules can be checked to see if they match, by running the rule's ``check()`` method. This returns a boolean indicating whether the rule was matched or not. >>> mlist = create_list('_xtest@example.com') >>> msg = message_from_string("""\ ... From: aperson@example.com ... ... An important message. ... """) For example, the ``emergency`` rule just checks to see if the emergency flag is set on the mailing list, and the message has not been pre-approved by the list administrator. >>> print(rule.name) emergency >>> mlist.emergency = False >>> rule.check(mlist, msg, {}) False >>> mlist.emergency = True >>> rule.check(mlist, msg, {}) True >>> rule.check(mlist, msg, dict(moderator_approved=True)) False .. toctree:: :glob: ./* mailman-3.1.1/src/mailman/rules/docs/max-size.rst0000664000175000017500000000222512632220112023020 0ustar maxkingmaxking00000000000000============ Message size ============ The ``message-size`` rule matches when the posted message is bigger than a specified maximum. Generally this is used to prevent huge attachments from getting posted to the list. This value is calculated in terms of KB (1024 bytes). >>> mlist = create_list('_xtest@example.com') >>> rule = config.rules['max-size'] >>> print(rule.name) max-size For example, setting the maximum message size to 1 means that any message bigger than that will match the rule. >>> mlist.max_message_size = 1 # 1024 bytes >>> one_line = 'x' * 79 >>> big_body = '\n'.join([one_line] * 15) >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: _xtest@example.com ... ... """ + big_body) >>> rule.check(mlist, msg, {}) True Setting the maximum message size to zero means no size check is performed. >>> mlist.max_message_size = 0 >>> rule.check(mlist, msg, {}) False Of course, if the maximum size is larger than the message's size, then it's still okay. >>> mlist.max_message_size = msg.original_size/1024.0 + 1 >>> rule.check(mlist, msg, {}) False mailman-3.1.1/src/mailman/rules/docs/header-matching.rst0000664000175000017500000001470212754757146024341 0ustar maxkingmaxking00000000000000=============== Header matching =============== Mailman can do pattern based header matching during its normal rule processing. There is a set of site-wide default header matches specified in the configuration file under the `[antispam]` section. >>> mlist = create_list('test@example.com') In this section, the variable `header_checks` contains a list of the headers to check, and the patterns to check them against. By default, this list is empty. It is also possible to programmatically extend these header checks. Here, we'll extend the checks with a pattern that matches 4 or more stars. >>> chain = config.chains['header-match'] >>> chain.extend('x-spam-score', '[*]{4,}') First, if the message has no ``X-Spam-Score:`` header, the message passes through the chain with no matches. >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: test@example.com ... Subject: Not spam ... Message-ID: ... ... This is a message. ... """) .. Function to help with printing rule hits and misses. >>> def hits_and_misses(msgdata): ... hits = msgdata.get('rule_hits', []) ... if len(hits) == 0: ... print('No rules hit') ... else: ... print('Rule hits:') ... for rule_name in hits: ... rule = config.rules[rule_name] ... print(' {}: {}'.format(rule.header, rule.pattern)) ... misses = msgdata.get('rule_misses', []) ... if len(misses) == 0: ... print('No rules missed') ... else: ... print('Rule misses:') ... for rule_name in misses: ... rule = config.rules[rule_name] ... print(' {}: {}'.format(rule.header, rule.pattern)) By looking at the message metadata after chain processing, we can see that none of the rules matched. >>> from mailman.core.chains import process >>> msgdata = {} >>> process(mlist, msg, msgdata, 'header-match') >>> hits_and_misses(msgdata) No rules hit Rule misses: x-spam-score: [*]{4,} The header may exist but does not match the pattern. >>> msg['X-Spam-Score'] = '***' >>> msgdata = {} >>> process(mlist, msg, msgdata, 'header-match') >>> hits_and_misses(msgdata) No rules hit Rule misses: x-spam-score: [*]{4,} The header may exist and match the pattern. By default, when the header matches, it gets held for moderator approval. :: >>> from mailman.interfaces.chain import ChainEvent >>> from mailman.testing.helpers import event_subscribers >>> def handler(event): ... if isinstance(event, ChainEvent): ... print(event.__class__.__name__, ... event.chain.name, event.msg['message-id']) >>> del msg['x-spam-score'] >>> msg['X-Spam-Score'] = '*****' >>> msgdata = {} >>> with event_subscribers(handler): ... process(mlist, msg, msgdata, 'header-match') HoldEvent hold >>> hits_and_misses(msgdata) Rule hits: x-spam-score: [*]{4,} No rules missed The configuration file can also specify a different final disposition for messages that match their header checks. For example, we may just want to discard such messages. >>> from mailman.testing.helpers import configuration >>> msgdata = {} >>> with event_subscribers(handler): ... with configuration('antispam', jump_chain='discard'): ... process(mlist, msg, msgdata, 'header-match') DiscardEvent discard These programmatically added headers can be removed by flushing the chain. Now, nothing with match this message. >>> chain.flush() >>> msgdata = {} >>> process(mlist, msg, msgdata, 'header-match') >>> hits_and_misses(msgdata) No rules hit No rules missed List-specific header matching ============================= Each mailing list can also be configured with a set of header matching regular expression rules. These can be used to impose list-specific header filtering with the same semantics as the global ``[antispam]`` section, or to have a different action. To follow the global antispam action, the header match rule must not specify a ``chain`` to jump to. If the default antispam action is changed in the configuration file and Mailman is restarted, those rules will get the new jump action. The list administrator wants to match not on four stars, but on three plus signs, but only for the current mailing list. >>> from mailman.interfaces.mailinglist import IHeaderMatchList >>> header_matches = IHeaderMatchList(mlist) >>> header_matches.append('x-spam-score', '[+]{3,}') A message with a spam score of two pluses does not match. >>> msgdata = {} >>> del msg['x-spam-score'] >>> msg['X-Spam-Score'] = '++' >>> process(mlist, msg, msgdata, 'header-match') >>> hits_and_misses(msgdata) No rules hit Rule misses: x-spam-score: [+]{3,} But a message with a spam score of three pluses does match. Because a message with the previous ``Message-Id`` is already in the moderation queue, we need to give this message a new ``Message-Id``. >>> msgdata = {} >>> del msg['x-spam-score'] >>> msg['X-Spam-Score'] = '+++' >>> del msg['message-id'] >>> msg['Message-Id'] = '' >>> process(mlist, msg, msgdata, 'header-match') >>> hits_and_misses(msgdata) Rule hits: x-spam-score: [+]{3,} No rules missed As does a message with a spam score of four pluses. >>> msgdata = {} >>> del msg['x-spam-score'] >>> msg['X-Spam-Score'] = '++++' >>> del msg['message-id'] >>> msg['Message-Id'] = '' >>> process(mlist, msg, msgdata, 'header-match') >>> hits_and_misses(msgdata) Rule hits: x-spam-score: [+]{3,} No rules missed Now, the list administrator wants to match on three plus signs, but wants those emails to be discarded instead of held. >>> header_matches.remove('x-spam-score', '[+]{3,}') >>> header_matches.append('x-spam-score', '[+]{3,}', 'discard') A message with a spam score of three pluses will still match, and the message will be discarded. >>> msgdata = {} >>> del msg['x-spam-score'] >>> msg['X-Spam-Score'] = '+++' >>> del msg['message-id'] >>> msg['Message-Id'] = '' >>> with event_subscribers(handler): ... process(mlist, msg, msgdata, 'header-match') DiscardEvent discard >>> hits_and_misses(msgdata) Rule hits: x-spam-score: [+]{3,} No rules missed mailman-3.1.1/src/mailman/rules/docs/truth.rst0000664000175000017500000000033312632220112022427 0ustar maxkingmaxking00000000000000===== Truth ===== This rule always matches. This makes it useful as a terminus rule for unconditionally jumping to another chain. >>> rule = config.rules['truth'] >>> rule.check(False, False, False) True mailman-3.1.1/src/mailman/rules/docs/suspicious.rst0000664000175000017500000000211212632220112023464 0ustar maxkingmaxking00000000000000================== Suspicious headers ================== Suspicious headers are a way for Mailman to hold messages that match a particular regular expression. This mostly historical feature is fairly confusing to users, and the list attribute that controls this is misnamed. >>> mlist = create_list('_xtest@example.com') >>> rule = config.rules['suspicious-header'] >>> print(rule.name) suspicious-header Set the so-called suspicious header configuration variable. >>> mlist.bounce_matching_headers = 'From: .*person@(blah.)?example.com' >>> msg = message_from_string("""\ ... From: aperson@example.com ... To: _xtest@example.com ... Subject: An implicit message ... ... """) >>> rule.check(mlist, msg, {}) True But if the header doesn't match the regular expression, the rule won't match. This one comes from a ``.org`` address. >>> msg = message_from_string("""\ ... From: aperson@example.org ... To: _xtest@example.com ... Subject: An implicit message ... ... """) >>> rule.check(mlist, msg, {}) False mailman-3.1.1/src/mailman/rules/docs/implicit-dest.rst0000664000175000017500000000627212632220112024040 0ustar maxkingmaxking00000000000000==================== Implicit destination ==================== The ``implicit-dest`` rule matches when the mailing list's posting address is not explicitly mentioned in the set of message recipients. >>> mlist = create_list('_xtest@example.com') >>> rule = config.rules['implicit-dest'] >>> print(rule.name) implicit-dest In order to check for implicit destinations, we need to adapt the mailing list to the appropriate interface. >>> from mailman.interfaces.mailinglist import IAcceptableAliasSet >>> alias_set = IAcceptableAliasSet(mlist) This rule matches messages that have an implicit destination, meaning that the mailing list's posting address isn't included in the explicit recipients. :: >>> mlist.require_explicit_destination = True >>> alias_set.clear() >>> msg = message_from_string("""\ ... From: aperson@example.org ... Subject: An implicit message ... ... """) >>> rule.check(mlist, msg, {}) True You can disable implicit destination checks for the mailing list. >>> mlist.require_explicit_destination = False >>> rule.check(mlist, msg, {}) False Even with some recipients, if the posting address is not included, the rule will match. >>> mlist.require_explicit_destination = True >>> msg['To'] = 'myfriend@example.com' >>> rule.check(mlist, msg, {}) True Add the posting address as a recipient and the rule will no longer match. >>> msg['Cc'] = '_xtest@example.com' >>> rule.check(mlist, msg, {}) False Alternatively, if one of the acceptable aliases is in the recipients list, then the rule will not match. :: >>> del msg['cc'] >>> rule.check(mlist, msg, {}) True >>> alias_set.add('myfriend@example.com') >>> rule.check(mlist, msg, {}) False A message gated from NNTP will obviously have an implicit destination. Such gated messages will not be held for implicit destination because it's assumed that Mailman pulled it from the appropriate news group. >>> rule.check(mlist, msg, dict(from_usenet=True)) False Additional aliases can be added. :: >>> alias_set.add('other@example.com') >>> del msg['to'] >>> rule.check(mlist, msg, {}) True >>> msg['To'] = 'other@example.com' >>> rule.check(mlist, msg, {}) False Aliases can be removed. >>> alias_set.remove('other@example.com') >>> rule.check(mlist, msg, {}) True Aliases can also be cleared. :: >>> msg['Cc'] = 'myfriend@example.com' >>> rule.check(mlist, msg, {}) False >>> alias_set.clear() >>> rule.check(mlist, msg, {}) True Alias patterns ============== It's also possible to specify an alias pattern, i.e. a regular expression to match against the recipients. For example, we can say that if there is a recipient in the ``example.net`` domain, then the rule does not match. :: >>> alias_set.add('^.*@example.net') >>> rule.check(mlist, msg, {}) True >>> msg['To'] = 'you@example.net' >>> rule.check(mlist, msg, {}) False Bad aliases =========== You cannot add an alias that looks like neither a pattern nor an email address. >>> alias_set.add('foobar') Traceback (most recent call last): ... ValueError: foobar mailman-3.1.1/src/mailman/rules/docs/approved.rst0000664000175000017500000002275212632220112023112 0ustar maxkingmaxking00000000000000===================== Pre-approved postings ===================== Messages can contain a pre-approval, which is used to bypass the normal message approval queue. This has several use cases: - A list administrator can send an emergency message to the mailing list from an unregistered address, for example if they are away from their normal email. - An automated script can be programmed to send a message to an otherwise moderated list. In order to support this, a mailing list can be given a *moderator password* which is shared among all the administrators. >>> mlist = create_list('test@example.com') This password will not be stored in clear text, so it must be hashed using the configured hash protocol. >>> mlist.moderator_password = config.password_context.encrypt( ... 'super secret') The ``approved`` rule determines whether the message contains the proper approval or not. >>> rule = config.rules['approved'] >>> print(rule.name) approved No approval =========== The preferred header to check for approval is ``Approved:``. If the message does not have this header, the rule will not match. >>> msg = message_from_string("""\ ... From: aperson@example.com ... ... An important message. ... """) >>> rule.check(mlist, msg, {}) False If the rule has an ``Approved`` header, but the value of this header does not match the moderator password, the rule will not match. Note that the header must contain the clear text version of the password. >>> msg['Approved'] = 'not the password' >>> rule.check(mlist, msg, {}) False The message is approved ======================= By adding an ``Approved`` header with a matching password, the rule will match. >>> del msg['approved'] >>> msg['Approved'] = 'super secret' >>> rule.check(mlist, msg, {}) True Alternative headers =================== Other headers can be used to stash the moderator password. This rule also checks the ``Approve`` header. >>> del msg['approved'] >>> msg['Approve'] = 'super secret' >>> rule.check(mlist, msg, {}) True Similarly, an ``X-Approved`` header can be used. >>> del msg['approve'] >>> msg['X-Approved'] = 'super secret' >>> rule.check(mlist, msg, {}) True And finally, an ``X-Approve`` header can be used. >>> del msg['x-approved'] >>> msg['X-Approve'] = 'super secret' >>> rule.check(mlist, msg, {}) True Removal of header ================= Technically, rules should not have side-effects, however this rule does remove the ``Approved`` header (LP: #973790) when it matches. >>> del msg['x-approved'] >>> msg['Approved'] = 'super secret' >>> rule.check(mlist, msg, {}) True >>> print(msg['approved']) None It also removes the header when it doesn't match. If the rule didn't do this, then the mailing list could be probed for its moderator password. >>> msg['Approved'] = 'not the password' >>> rule.check(mlist, msg, {}) False >>> print(msg['approved']) None Using a pseudo-header ===================== Mail programs have varying degrees to which they support custom headers like ``Approved:``. For this reason, Mailman also supports using a *pseudo-header*, which is really just the first non-whitespace line in the payload of the message. If this pseudo-header looks like a matching ``Approved:`` header, the message is similarly allowed to pass. >>> msg = message_from_string("""\ ... From: aperson@example.com ... ... Approved: super secret ... An important message. ... """) >>> rule.check(mlist, msg, {}) True The pseudo-header is always removed from the body of plain text messages. >>> print(msg.as_string()) From: aperson@example.com Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" An important message. As before, a mismatch in the pseudo-header does not approve the message, but the pseudo-header line is still removed. :: >>> msg = message_from_string("""\ ... From: aperson@example.com ... ... Approved: not the password ... An important message. ... """) >>> rule.check(mlist, msg, {}) False >>> print(msg.as_string()) From: aperson@example.com Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" An important message. MIME multipart support ====================== Mailman searches for the pseudo-header as the first non-whitespace line in the first ``text/plain`` message part of the message. This allows the feature to be used with MIME documents. >>> msg = message_from_string("""\ ... From: aperson@example.com ... MIME-Version: 1.0 ... Content-Type: multipart/mixed; boundary="AAA" ... ... --AAA ... Content-Type: application/x-ignore ... ... Approved: not the password ... The above line will be ignored. ... ... --AAA ... Content-Type: text/plain ... ... Approved: super secret ... An important message. ... --AAA-- ... """) >>> rule.check(mlist, msg, {}) True Like before, the pseudo-header is removed, but only from the text parts. >>> print(msg.as_string()) From: aperson@example.com MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="AAA" --AAA Content-Type: application/x-ignore Approved: not the password The above line will be ignored. --AAA Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" An important message. --AAA-- If the correct password is in the non-``text/plain`` part, it is ignored. >>> msg = message_from_string("""\ ... From: aperson@example.com ... MIME-Version: 1.0 ... Content-Type: multipart/mixed; boundary="AAA" ... ... --AAA ... Content-Type: application/x-ignore ... ... Approved: super secret ... The above line will be ignored. ... ... --AAA ... Content-Type: text/plain ... ... Approved: not the password ... An important message. ... --AAA-- ... """) >>> rule.check(mlist, msg, {}) False Pseudo-header is still stripped, but only from the ``text/plain`` part. >>> print(msg.as_string()) From: aperson@example.com MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="AAA" --AAA Content-Type: application/x-ignore Approved: super secret The above line will be ignored. --AAA Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" An important message. --AAA-- Stripping text/html parts ========================= Because some mail programs will include both a ``text/plain`` part and a ``text/html`` alternative, the rule must search the alternatives and strip anything that looks like an ``Approved:`` header. >>> msg = message_from_string("""\ ... From: aperson@example.com ... MIME-Version: 1.0 ... Content-Type: multipart/mixed; boundary="AAA" ... ... --AAA ... Content-Type: text/html ... ... ... ... ... Approved: super secret ...

The above line will be ignored. ... ... ... ... --AAA ... Content-Type: text/plain ... ... Approved: super secret ... An important message. ... --AAA-- ... """) >>> rule.check(mlist, msg, {}) True And the header-like text in the ``text/html`` part was stripped. >>> print(msg.as_string()) From: aperson@example.com MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="AAA" --AAA Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Content-Type: text/html; charset="us-ascii"

The above line will be ignored. --AAA Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" An important message. --AAA-- This is true even if the rule does not match (i.e. the incorrect password was given). :: >>> msg = message_from_string("""\ ... From: aperson@example.com ... MIME-Version: 1.0 ... Content-Type: multipart/mixed; boundary="AAA" ... ... --AAA ... Content-Type: text/html ... ... ... ... ... Approved: not the password ...

The above line will be ignored. ... ... ... ... --AAA ... Content-Type: text/plain ... ... Approved: not the password ... An important message. ... --AAA-- ... """) >>> rule.check(mlist, msg, {}) False >>> print(msg.as_string()) From: aperson@example.com MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="AAA" --AAA Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Content-Type: text/html; charset="us-ascii"

The above line will be ignored. --AAA Content-Transfer-Encoding: 7bit MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" An important message. --AAA-- mailman-3.1.1/src/mailman/rules/docs/moderation.rst0000664000175000017500000001414513203223435023436 0ustar maxkingmaxking00000000000000========== Moderation ========== All members and nonmembers have a moderation action, which defaults to the appropriate list's default action. When the action is not `defer`, the `moderation` rule flags the message as needing moderation. This might be to automatically accept, discard, reject, or hold the message. Two separate rules check for member and nonmember moderation. Member moderation happens early in the built-in chain, while nonmember moderation happens later in the chain, after normal moderation checks. >>> mlist = create_list('test@example.com') Member moderation ================= >>> member_rule = config.rules['member-moderation'] >>> print(member_rule.name) member-moderation Anne, a mailing list member, sends a message to the mailing list. Her moderation action is not set. >>> from mailman.testing.helpers import subscribe >>> member = subscribe(mlist, 'Anne') >>> member on test@example.com as MemberRole.member> >>> print(member.moderation_action) None Because the list's default member action is set to `defer`, Anne's posting is not moderated. >>> print(mlist.default_member_action) Action.defer Because Anne is not moderated, the member moderation rule does not match. >>> member_msg = message_from_string("""\ ... From: aperson@example.com ... To: test@example.com ... Subject: A posted message ... ... """) >>> member_rule.check(mlist, member_msg, {}) False Once the member's moderation action is set to something other than `defer` or ``None`` (given the list's current default member moderation action), the rule matches. Also, the message metadata has a few extra pieces of information for the eventual moderation chain. >>> from mailman.interfaces.action import Action >>> member.moderation_action = Action.hold >>> msgdata = {} >>> member_rule.check(mlist, member_msg, msgdata) True >>> dump_msgdata(msgdata) member_moderation_action: hold moderation_reasons : ['The message comes from a moderated member'] moderation_sender : aperson@example.com Nonmembers ========== Nonmembers are handled in a similar way, although by default, nonmember postings are held for moderator approval. >>> nonmember_rule = config.rules['nonmember-moderation'] >>> print(nonmember_rule.name) nonmember-moderation Bart, who is not a member of the mailing list, sends a message to the list. He has no explicit nonmember moderation action. >>> from mailman.interfaces.member import MemberRole >>> nonmember = subscribe(mlist, 'Bart', MemberRole.nonmember) >>> nonmember on test@example.com as MemberRole.nonmember> >>> print(nonmember.moderation_action) None The list's default nonmember moderation action is to hold postings by nonmembers. >>> print(mlist.default_nonmember_action) Action.hold Since Bart is registered as a nonmember of the list, and his moderation action is set to None, the action falls back to the list's default nonmember moderation action, which is to hold the post for moderator approval. Thus the rule matches and the message metadata again carries some useful information. >>> nonmember_msg = message_from_string("""\ ... From: bperson@example.com ... To: test@example.com ... Subject: A posted message ... ... """) >>> msgdata = {} >>> nonmember_rule.check(mlist, nonmember_msg, msgdata) True >>> dump_msgdata(msgdata) member_moderation_action: hold moderation_reasons : ['The message is not from a list member'] moderation_sender : bperson@example.com Of course, the nonmember action can be set to defer the decision, in which case the rule does not match. >>> nonmember.moderation_action = Action.defer >>> nonmember_rule.check(mlist, nonmember_msg, {}) False Unregistered nonmembers ======================= The incoming runner ensures that all sender addresses are registered in the system, but it is the moderation rule that subscribes nonmember addresses to the mailing list if they are not already subscribed. :: >>> from mailman.interfaces.usermanager import IUserManager >>> from zope.component import getUtility >>> address = getUtility(IUserManager).create_address( ... 'cperson@example.com') >>> address >>> msg = message_from_string("""\ ... From: cperson@example.com ... To: test@example.com ... Subject: A posted message ... ... """) cperson is neither a member, nor a nonmember of the mailing list. :: >>> def memberkey(member): ... return member.mailing_list, member.address.email, member.role.value >>> dump_list(mlist.members.members, key=memberkey) on test@example.com as MemberRole.member> >>> dump_list(mlist.nonmembers.members, key=memberkey) on test@example.com as MemberRole.nonmember> However, when the nonmember moderation rule runs, it adds the cperson as a nonmember of the list. The rule also matches. >>> msgdata = {} >>> nonmember_rule.check(mlist, msg, msgdata) True >>> dump_msgdata(msgdata) member_moderation_action: hold moderation_reasons : ['The message is not from a list member'] moderation_sender : cperson@example.com >>> dump_list(mlist.members.members, key=memberkey) on test@example.com as MemberRole.member> >>> dump_list(mlist.nonmembers.members, key=memberkey) on test@example.com as MemberRole.nonmember> Cross-membership checks ======================= Of course, the member moderation rule does not match for nonmembers... >>> member_rule.check(mlist, nonmember_msg, {}) False >>> nonmember_rule.check(mlist, member_msg, {}) False mailman-3.1.1/src/mailman/rules/docs/administrivia.rst0000664000175000017500000000524312632220112024131 0ustar maxkingmaxking00000000000000============= Administrivia ============= The `administrivia` rule matches when the message contains some common email commands in the ``Subject:`` header or first few lines of the payload. This is used to catch messages posted to the list which should have been sent to the ``-request`` robot address. >>> mlist = create_list('_xtest@example.com') >>> mlist.administrivia = True >>> rule = config.rules['administrivia'] >>> print(rule.name) administrivia For example, if the ``Subject:`` header contains the word ``unsubscribe``, the rule matches. >>> msg_1 = message_from_string("""\ ... From: aperson@example.com ... Subject: unsubscribe ... ... """) >>> rule.check(mlist, msg_1, {}) True Similarly, if the body of the message contains the word ``subscribe`` in the first few lines of text, the rule matches. >>> msg_2 = message_from_string("""\ ... From: aperson@example.com ... Subject: I wish to join your list ... ... subscribe ... """) >>> rule.check(mlist, msg_2, {}) True In both cases, administrivia checking can be disabled. >>> mlist.administrivia = False >>> rule.check(mlist, msg_1, {}) False >>> rule.check(mlist, msg_2, {}) False To make the administrivia heuristics a little more robust, the rule actually looks for a minimum and maximum number of arguments, so that it really does seem like a mis-addressed email command. In this case, the ``confirm`` command requires at least one argument. We don't give that here so the rule will not match. >>> mlist.administrivia = True >>> msg = message_from_string("""\ ... From: aperson@example.com ... Subject: confirm ... ... """) >>> rule.check(mlist, msg, {}) False But a real ``confirm`` message will match. >>> msg = message_from_string("""\ ... From: aperson@example.com ... Subject: confirm 12345 ... ... """) >>> rule.check(mlist, msg, {}) True We don't show all the other possible email commands, but you get the idea. Non-administrivia ================= Of course, messages that don't contain administrivia, don't match the rule. >>> msg = message_from_string("""\ ... From: aperson@example.com ... Subject: examine ... ... persuade ... """) >>> rule.check(mlist, msg, {}) False Also, only ``text/plain`` parts are checked for administrivia, so any email commands in other content type subparts are ignored. >>> msg = message_from_string("""\ ... From: aperson@example.com ... Subject: some administrivia ... Content-Type: text/x-special ... ... subscribe ... """) >>> rule.check(mlist, msg, {}) False mailman-3.1.1/src/mailman/rules/docs/news-moderation.rst0000664000175000017500000000232212632220112024374 0ustar maxkingmaxking00000000000000==================== Newsgroup moderation ==================== The ``news-moderation`` rule matches all messages posted to mailing lists that gateway to a moderated newsgroup. The reason for this is that such messages must get forwarded on to the newsgroup moderator. From there it will get posted to the newsgroup, and from there, gated to the mailing list. It's a circuitous route, but it works nonetheless by holding all messages posted directly to the mailing list. >>> mlist = create_list('_xtest@example.com') >>> rule = config.rules['news-moderation'] >>> print(rule.name) news-moderation Set the list configuration variable to enable newsgroup moderation. >>> from mailman.interfaces.nntp import NewsgroupModeration >>> mlist.newsgroup_moderation = NewsgroupModeration.moderated And now all messages will match the rule. >>> msg = message_from_string("""\ ... From: aperson@example.org ... Subject: An announcement ... ... Great things are happening. ... """) >>> rule.check(mlist, msg, {}) True When moderation is turned off, the rule does not match. >>> mlist.newsgroup_moderation = NewsgroupModeration.none >>> rule.check(mlist, msg, {}) False mailman-3.1.1/src/mailman/rules/docs/loop.rst0000664000175000017500000000247212632220112022240 0ustar maxkingmaxking00000000000000============= Posting loops ============= To avoid a posting loop, Mailman has a rule to check for the existence of an RFC 2369 ``List-Post:`` header with the value of the list's posting address. >>> mlist = create_list('_xtest@example.com') >>> rule = config.rules['loop'] >>> print(rule.name) loop The header could be missing, in which case the rule does not match. >>> msg = message_from_string("""\ ... From: aperson@example.com ... ... An important message. ... """) >>> rule.check(mlist, msg, {}) False The header could be present, but not match the list's posting address. >>> msg['List-Post'] = 'not-this-list@example.com' >>> rule.check(mlist, msg, {}) False If the header is present and does match the posting address, the rule matches. >>> del msg['list-post'] >>> msg['List-Post'] = mlist.posting_address >>> rule.check(mlist, msg, {}) True Even if there are multiple ``List-Post:`` headers, as long as one with the posting address exists, the rule matches. >>> msg = message_from_string("""\ ... From: aperson@example.com ... List-Post: not-this-list@example.com ... List-Post: _xtest@example.com ... List-Post: foo@example.com ... ... An important message. ... """) >>> rule.check(mlist, msg, {}) True mailman-3.1.1/src/mailman/rules/dmarc.py0000664000175000017500000003166013203705633021261 0ustar maxkingmaxking00000000000000# Copyright (C) 2016-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """DMARC mitigation rule.""" import os import re import logging import dns.resolver from dns.exception import DNSException from email.utils import parseaddr from lazr.config import as_timedelta from mailman.config import config from mailman.core.i18n import _ from mailman.interfaces.mailinglist import DMARCMitigateAction from mailman.interfaces.rules import IRule from mailman.utilities.datetime import now from mailman.utilities.protocols import get from mailman.utilities.string import wrap from pkg_resources import resource_string as resource_bytes from public import public from requests.exceptions import HTTPError from urllib.error import URLError from zope.interface import implementer elog = logging.getLogger('mailman.error') vlog = logging.getLogger('mailman.vette') DOT = '.' EMPTYSTRING = '' KEEP_LOOKING = object() LOCAL_FILE_NAME = 'public_suffix_list.dat' # Map organizational domain suffix rules to a boolean indicating whether the # rule is an exception or not. suffix_cache = dict() def ensure_current_suffix_list(): # Read and parse the organizational domain suffix list. First look in the # cached directory to see if we already have a valid copy of it. cached_copy_path = os.path.join(config.VAR_DIR, LOCAL_FILE_NAME) lifetime = as_timedelta(config.dmarc.cache_lifetime) download = False try: mtime = os.stat(cached_copy_path).st_mtime except FileNotFoundError: vlog.info('No cached copy of the public suffix list found') download = True cache_found = False else: cache_found = True # Is the cached copy out-of-date? Note that when we write a new cache # version we explicitly set its mtime to the time in the future when # the cache will expire. if mtime < now().timestamp(): download = True vlog.info('Cached copy of public suffix list is out of date') if download: try: content = get(config.dmarc.org_domain_data_url) except (URLError, HTTPError) as error: elog.error('Unable to retrieve public suffix list from %s: %s', config.dmarc.org_domain_data_url, getattr(error, 'reason', str(error))) if cache_found: vlog.info('Using out of date public suffix list') content = None else: # We couldn't access the URL and didn't even have an out of # date suffix list cached. Use the shipped version. content = resource_bytes('mailman.rules.data', LOCAL_FILE_NAME) if content is not None: # Content is either a string or UTF-8 encoded bytes. if isinstance(content, bytes): content = content.decode('utf-8') # Write the cache atomically. new_path = cached_copy_path + '.new' with open(new_path, 'w', encoding='utf-8') as fp: fp.write(content) # Set the expiry time to the future. mtime = (now() + lifetime).timestamp() os.utime(new_path, (mtime, mtime)) # Flip the new file into the cached location. This does not # modify the mtime. os.rename(new_path, cached_copy_path) return cached_copy_path def parse_suffix_list(filename=None): # Parse the suffix list into a per process cache. if filename is None: filename = ensure_current_suffix_list() # At this point the cached copy must exist and is as valid as possible. # Read and return the contents as a UTF-8 string. with open(filename, 'r', encoding='utf-8') as fp: for line in fp: if not line.strip() or line.startswith('//'): continue line = re.sub('\s.*', '', line) if not line: continue parts = line.lower().split('.') if parts[0].startswith('!'): exception = True parts = [parts[0][1:]] + parts[1:] else: exception = False parts.reverse() key = DOT.join(parts) suffix_cache[key] = exception def get_domain(parts, label): # A helper to get a domain name consisting of the first label+1 labels in # parts. domain = parts[:min(label+1, len(parts))] domain.reverse() return DOT.join(domain) def get_organizational_domain(domain): # Given a domain name, this returns the corresponding Organizational # Domain which may be the same as the input. if len(suffix_cache) == 0: parse_suffix_list() hits = [] parts = domain.lower().split('.') parts.reverse() for key in suffix_cache: key_parts = key.split('.') if len(parts) >= len(key_parts): for i in range(len(key_parts) - 1): if parts[i] != key_parts[i] and key_parts[i] != '*': break else: if (parts[len(key_parts) - 1] == key_parts[-1] or key_parts[-1] == '*'): hits.append(key) if not hits: return get_domain(parts, 1) label = 0 for key in hits: key_parts = key.split('.') if suffix_cache[key]: # It's an exception. return get_domain(parts, len(key_parts) - 1) if len(key_parts) > label: label = len(key_parts) return get_domain(parts, label) def is_reject_or_quarantine(mlist, email, dmarc_domain, org=False): # This takes a mailing list, an email address as in the From: header, the # _dmarc host name for the domain in question, and a flag stating whether # we should check the organizational domains. It returns one of three # values: # * True if the DMARC policy is reject or quarantine; # * False if is not; # * A special sentinel if we should continue looking resolver = dns.resolver.Resolver() resolver.timeout = as_timedelta( config.dmarc.resolver_timeout).total_seconds() resolver.lifetime = as_timedelta( config.dmarc.resolver_lifetime).total_seconds() try: txt_recs = resolver.query(dmarc_domain, dns.rdatatype.TXT) except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): return KEEP_LOOKING except DNSException as error: elog.error( 'DNSException: Unable to query DMARC policy for %s (%s). %s', email, dmarc_domain, error.__doc__) return KEEP_LOOKING # Be as robust as possible in parsing the result. results_by_name = {} cnames = {} want_names = set([dmarc_domain + '.']) # Check all the TXT records returned by DNS. Keep track of the CNAMEs for # checking later on. Ignore any other non-TXT records. for txt_rec in txt_recs.response.answer: if txt_rec.rdtype == dns.rdatatype.CNAME: cnames[txt_rec.name.to_text()] = ( txt_rec.items[0].target.to_text()) if txt_rec.rdtype != dns.rdatatype.TXT: continue result = EMPTYSTRING.join( str(record, encoding='utf-8') for record in txt_rec.items[0].strings) name = txt_rec.name.to_text() results_by_name.setdefault(name, []).append(result) expands = list(want_names) seen = set(expands) while expands: item = expands.pop(0) if item in cnames: if cnames[item] in seen: # CNAME loop. continue expands.append(cnames[item]) seen.add(cnames[item]) want_names.add(cnames[item]) want_names.discard(item) assert len(want_names) == 1, ( 'Error in CNAME processing for {}; want_names != 1.'.format( dmarc_domain)) for name in want_names: if name not in results_by_name: continue dmarcs = [ record for record in results_by_name[name] if record.startswith('v=DMARC1;') ] if len(dmarcs) == 0: return KEEP_LOOKING if len(dmarcs) > 1: elog.error( 'RRset of TXT records for %s has %d v=DMARC1 entries; ' 'testing them all', dmarc_domain, len(dmarcs)) for entry in dmarcs: mo = re.search(r'\bsp=(\w*)\b', entry, re.IGNORECASE) if org and mo: policy = mo.group(1).lower() else: mo = re.search(r'\bp=(\w*)\b', entry, re.IGNORECASE) if mo: policy = mo.group(1).lower() else: # This continue does actually get covered by # TestDMARCRules.test_domain_with_subdomain_policy() and # TestDMARCRules.test_no_policy() but because of # Coverage BitBucket issue #198 and # http://bugs.python.org/issue2506 coverage cannot report # it as such, so just pragma it away. continue # pragma: no cover if policy in ('reject', 'quarantine'): vlog.info( '%s: DMARC lookup for %s (%s) found p=%s in %s = %s', mlist.list_name, email, dmarc_domain, policy, name, entry) return True return False def maybe_mitigate(mlist, email): # This takes an email address, and returns True if DMARC policy is # p=reject or p=quarantine. email = email.lower() # Scan from the right in case quoted local part has an '@'. local, at, from_domain = email.rpartition('@') if at != '@': return False answer = is_reject_or_quarantine( mlist, email, '_dmarc.{}'.format(from_domain)) if answer is not KEEP_LOOKING: return answer org_dom = get_organizational_domain(from_domain) if org_dom != from_domain: answer = is_reject_or_quarantine( mlist, email, '_dmarc.{}'.format(org_dom), org=True) if answer is not KEEP_LOOKING: return answer return False @public @implementer(IRule) class DMARCMitigation: """The DMARC mitigation rule.""" name = 'dmarc-mitigation' description = _('Find DMARC policy of From: domain.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" if mlist.dmarc_mitigate_action is DMARCMitigateAction.no_mitigation: # Don't bother to check if we're not going to do anything. return False display_name, address = parseaddr(msg.get('from')) if maybe_mitigate(mlist, address): # If dmarc_mitigate_action is discard or reject, this rule fires # and jumps to the 'moderation' chain to do the actual discard. # Otherwise, the rule misses but sets a flag for the dmarc handler # to do the appropriate action. msgdata['dmarc'] = True if mlist.dmarc_mitigate_action is DMARCMitigateAction.discard: msgdata['dmarc_action'] = 'discard' with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append( _('DMARC moderation')) elif mlist.dmarc_mitigate_action is DMARCMitigateAction.reject: listowner = mlist.owner_address # noqa F841 with _.defer_translation(): # This will be translated at the point of use. reason = (mlist.dmarc_moderation_notice or _( 'You are not allowed to post to this mailing ' 'list From: a domain which publishes a DMARC ' 'policy of reject or quarantine, and your message' ' has been automatically rejected. If you think ' 'that your messages are being rejected in error, ' 'contact the mailing list owner at ${listowner}.')) msgdata.setdefault('moderation_reasons', []).append( wrap(reason)) msgdata['dmarc_action'] = 'reject' else: return False msgdata['moderation_sender'] = address return True return False mailman-3.1.1/src/mailman/rules/suspicious.py0000664000175000017500000000724613203223435022377 0ustar maxkingmaxking00000000000000# Copyright (C) 2007-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The historical 'suspicious header' rule.""" import re import logging from mailman.core.i18n import _ from mailman.interfaces.rules import IRule from public import public from zope.interface import implementer log = logging.getLogger('mailman.error') @public @implementer(IRule) class SuspiciousHeader: """The historical 'suspicious header' rule.""" name = 'suspicious-header' description = _('Catch messages with suspicious headers.') record = True def check(self, mlist, msg, msgdata): """See `IRule`.""" return (mlist.bounce_matching_headers and has_matching_bounce_header(mlist, msg, msgdata)) def _parse_matching_header_opt(mlist): """Return a list of triples [(field name, regex, line), ...].""" # - Blank lines and lines with '#' as first char are skipped. # - Leading whitespace in the matchexp is trimmed - you can defeat # that by, eg, containing it in gratuitous square brackets. all = [] for line in mlist.bounce_matching_headers.splitlines(): line = line.strip() # Skip blank lines and lines *starting* with a '#'. if not line or line.startswith('#'): continue i = line.find(':') if i < 0: # This didn't look like a header line. BAW: should do a # better job of informing the list admin. log.error('bad bounce_matching_header line: %s\n%s', mlist.display_name, line) else: header = line[:i] value = line[i+1:].lstrip() try: cre = re.compile(value, re.IGNORECASE) except re.error as error: # The regexp was malformed. BAW: should do a better # job of informing the list admin. log.error("""\ bad regexp in bounce_matching_header line: %s \n%s (cause: %s)""", mlist.display_name, value, error) else: all.append((header, cre, line)) return all def has_matching_bounce_header(mlist, msg, msgdata): """Does the message have a matching bounce header? :param mlist: The mailing list the message is destined for. :param msg: The email message object. :return: True if a header field matches a regexp in the bounce_matching_header mailing list variable. """ for header, cre, line in _parse_matching_header_opt(mlist): for value in msg.get_all(header, []): # Convert the header value to a str because it may be an # email.header.Header instance. if cre.search(str(value)): msgdata['moderation_sender'] = msg.sender with _.defer_translation(): # This will be translated at the point of use. msgdata.setdefault('moderation_reasons', []).append((_( 'Header "{}" matched a bounce_matching_header line'), str(value))) return True return False mailman-3.1.1/src/mailman/rest/0000775000175000017500000000000013204154702017432 5ustar maxkingmaxking00000000000000mailman-3.1.1/src/mailman/rest/preferences.py0000664000175000017500000000722113066532160022313 0ustar maxkingmaxking00000000000000# Copyright (C) 2011-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Preferences.""" from lazr.config import as_boolean from mailman.interfaces.member import DeliveryMode, DeliveryStatus from mailman.rest.helpers import ( GetterSetter, bad_request, etag, no_content, not_found, okay) from mailman.rest.validator import ( Validator, enum_validator, language_validator) from public import public PREFERENCES = ( 'acknowledge_posts', 'delivery_mode', 'delivery_status', 'hide_address', 'preferred_language', 'receive_list_copy', 'receive_own_postings', ) @public class ReadOnlyPreferences: """...//preferences""" def __init__(self, parent, base_url): self._parent = parent self._base_url = base_url def on_get(self, request, response): resource = dict() for attr in PREFERENCES: # Handle this one specially. if attr == 'preferred_language': continue value = getattr(self._parent, attr, None) if value is not None: resource[attr] = value # Add the preferred language, if it's not missing. preferred_language = self._parent.preferred_language if preferred_language is not None: resource['preferred_language'] = preferred_language.code # Add the self link. resource['self_link'] = self.api.path_to( '{}/preferences'.format(self._base_url)) okay(response, etag(resource)) @public class Preferences(ReadOnlyPreferences): """Preferences which can be changed.""" def patch_put(self, request, response, is_optional): if self._parent is None: not_found(response) return kws = dict( acknowledge_posts=GetterSetter(as_boolean), hide_address=GetterSetter(as_boolean), delivery_mode=GetterSetter(enum_validator(DeliveryMode)), delivery_status=GetterSetter(enum_validator(DeliveryStatus)), preferred_language=GetterSetter(language_validator), receive_list_copy=GetterSetter(as_boolean), receive_own_postings=GetterSetter(as_boolean), ) if is_optional: # For a PUT, all attributes are optional. kws['_optional'] = kws.keys() try: Validator(**kws).update(self._parent, request) except ValueError as error: bad_request(response, str(error)) else: no_content(response) def on_patch(self, request, response): """Patch the preferences.""" self.patch_put(request, response, is_optional=True) def on_put(self, request, response): """Change all preferences.""" self.patch_put(request, response, is_optional=False) def on_delete(self, request, response): """Delete all preferences.""" for attr in PREFERENCES: if hasattr(self._parent, attr): setattr(self._parent, attr, None) no_content(response) mailman-3.1.1/src/mailman/rest/users.py0000664000175000017500000004062113066532160021154 0ustar maxkingmaxking00000000000000# Copyright (C) 2011-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """REST for users.""" from functools import lru_cache from lazr.config import as_boolean from mailman.config import config from mailman.interfaces.address import ExistingAddressError from mailman.interfaces.usermanager import IUserManager from mailman.rest.addresses import UserAddresses from mailman.rest.helpers import ( BadRequest, CollectionMixin, GetterSetter, NotFound, bad_request, child, conflict, created, etag, forbidden, no_content, not_found, okay) from mailman.rest.preferences import Preferences from mailman.rest.validator import ( PatchValidator, ReadOnlyPATCHRequestError, UnknownPATCHRequestError, Validator, list_of_strings_validator) from passlib.utils import generate_password as generate from public import public from zope.component import getUtility # Attributes of a user which can be changed via the REST API. @public class PasswordEncrypterGetterSetter(GetterSetter): def __init__(self): super().__init__(config.password_context.encrypt) def get(self, obj, attribute): assert attribute == 'cleartext_password' super().get(obj, 'password') def put(self, obj, attribute, value): assert attribute == 'cleartext_password' super().put(obj, 'password', value) @public class ListOfDomainOwners(GetterSetter): def get(self, domain, attribute): assert attribute == 'owner', ( 'Unexpected attribute: {}'.format(attribute)) def sort_key(owner): # noqa: E306 return owner.addresses[0].email return sorted(domain.owners, key=sort_key) def put(self, domain, attribute, value): assert attribute == 'owner', ( 'Unexpected attribute: {}'.format(attribute)) domain.add_owners(value) ATTRIBUTES = dict( cleartext_password=PasswordEncrypterGetterSetter(), display_name=GetterSetter(str), is_server_owner=GetterSetter(as_boolean), ) CREATION_FIELDS = dict( display_name=str, email=str, is_server_owner=as_boolean, password=str, _optional=('display_name', 'password', 'is_server_owner'), ) def create_user(api, arguments, response): """Create a new user.""" # We can't pass the 'password' argument to the user creation method, so # strip that out (if it exists), then create the user, adding the password # after the fact if successful. password = arguments.pop('password', None) is_server_owner = arguments.pop('is_server_owner', False) user_manager = getUtility(IUserManager) try: user = user_manager.create_user(**arguments) except ExistingAddressError as error: # The address already exists. If the address already has a user # linked to it, raise an error, otherwise create a new user and link # it to this address. email = arguments.pop('email') user = user_manager.get_user(email) if user is None: address = user_manager.get_address(email) user = user_manager.create_user(**arguments) user.link(address) else: bad_request( response, 'User already exists: {}'.format(error.address)) return None if password is None: # This will have to be reset since it cannot be retrieved. password = generate(int(config.passwords.password_length)) user.password = config.password_context.encrypt(password) user.is_server_owner = is_server_owner user_id = api.from_uuid(user.user_id) location = api.path_to('users/{}'.format(user_id)) created(response, location) return user class _UserBase(CollectionMixin): """Shared base class for user representations.""" def _resource_as_dict(self, user): """See `CollectionMixin`.""" # The canonical URL for a user is their unique user id, although we # can always look up a user based on any registered and validated # email address associated with their account. The user id is a UUID, # but we serialize its integer equivalent. user_id = self.api.from_uuid(user.user_id) resource = dict( created_on=user.created_on, is_server_owner=user.is_server_owner, self_link=self.api.path_to('users/{}'.format(user_id)), user_id=user_id, ) # Add the password attribute, only if the user has a password. Same # with the real name. These could be None or the empty string. if user.password: resource['password'] = user.password if user.display_name: resource['display_name'] = user.display_name return resource def _get_collection(self, request): """See `CollectionMixin`.""" return list(getUtility(IUserManager).users) @public class AllUsers(_UserBase): """The users.""" def on_get(self, request, response): """/users""" resource = self._make_collection(request) okay(response, etag(resource)) def on_post(self, request, response): """Create a new user.""" try: validator = Validator(**CREATION_FIELDS) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return create_user(self.api, arguments, response) @public class AUser(_UserBase): """A user.""" def __init__(self, user_identifier): """Get a user by various type of identifiers. :param user_identifier: The identifier used to retrieve the user. The identifier may either be an email address controlled by the user or the UUID of the user. The type of identifier is auto-detected by looking for an `@` symbol, in which case it's taken as an email address, otherwise it's assumed to be a UUID. However, UUIDs in API 3.0 are integers, while in 3.1 are hex. :type user_identifier: string """ self._user_identifier = user_identifier # Defer calculation of the user until the API object is set, since # that will determine how to interpret the user identifier. For ease # of code migration, use an _user caching property (see below). @property @lru_cache(1) def _user(self): user_manager = getUtility(IUserManager) if '@' in self._user_identifier: return user_manager.get_user(self._user_identifier) else: # The identifier is the string representation of a UUID, either an # int in API 3.0 or a hex in API 3.1. try: user_id = self.api.to_uuid(self._user_identifier) except ValueError: return None else: return user_manager.get_user_by_id(user_id) def on_get(self, request, response): """Return a single user end-point.""" if self._user is None: not_found(response) else: okay(response, self._resource_as_json(self._user)) @child() def addresses(self, context, segments): """/users//addresses""" if self._user is None: return NotFound(), [] return UserAddresses(self._user) def on_delete(self, request, response): """Delete the named user and all associated resources.""" if self._user is None: not_found(response) return for member in self._user.memberships.members: member.unsubscribe() user_manager = getUtility(IUserManager) user_manager.delete_user(self._user) no_content(response) @child() def preferences(self, context, segments): """/users//preferences""" if len(segments) != 0: return BadRequest(), [] if self._user is None: return NotFound(), [] child = Preferences( self._user.preferences, 'users/{}'.format(self.api.from_uuid(self._user.user_id))) return child, [] def on_patch(self, request, response): """Patch the user's configuration (i.e. partial update).""" if self._user is None: not_found(response) return try: validator = PatchValidator(request, ATTRIBUTES) except UnknownPATCHRequestError as error: bad_request( response, b'Unknown attribute: {0}'.format(error.attribute)) except ReadOnlyPATCHRequestError as error: bad_request( response, b'Read-only attribute: {0}'.format(error.attribute)) else: validator.update(self._user, request) no_content(response) def on_put(self, request, response): """Put the user's configuration (i.e. full update).""" if self._user is None: not_found(response) return validator = Validator(**ATTRIBUTES) try: validator.update(self._user, request) except UnknownPATCHRequestError as error: bad_request( response, b'Unknown attribute: {0}'.format(error.attribute)) except ReadOnlyPATCHRequestError as error: bad_request( response, b'Read-only attribute: {0}'.format(error.attribute)) except ValueError as error: bad_request(response, str(error)) else: no_content(response) @child() def login(self, context, segments): """Log the user in, sort of, by verifying a given password.""" if self._user is None: return NotFound(), [] return Login(self._user) @public class AddressUser(_UserBase): """The user linked to an address.""" def __init__(self, address): self._address = address self._user = address.user def on_get(self, request, response): """Return a single user end-point.""" if self._user is None: not_found(response) else: okay(response, self._resource_as_json(self._user)) def on_delete(self, request, response): """Delete the named user, all her memberships, and addresses.""" if self._user is None: not_found(response) return self._user.unlink(self._address) no_content(response) def on_post(self, request, response): """Link a user to the address, and create it if needed.""" if self._user: conflict(response) return # When creating a linked user by POSTing, the user either must already # exist, or it can be automatically created, if the auto_create flag # is given and true (if missing, it defaults to true). However, in # this case we do not accept 'email' as a POST field. fields = CREATION_FIELDS.copy() del fields['email'] fields['user_id'] = self.api.to_uuid fields['auto_create'] = as_boolean fields['_optional'] = fields['_optional'] + ( 'user_id', 'auto_create', 'is_server_owner') try: validator = Validator(**fields) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return user_manager = getUtility(IUserManager) if 'user_id' in arguments: user_id = arguments['user_id'] user = user_manager.get_user_by_id(user_id) if user is None: bad_request(response, 'No user with ID {}'.format( self.api.from_uuid(user_id))) return okay(response) else: auto_create = arguments.pop('auto_create', True) if auto_create: # This sets the 201 or 400 status. user = create_user(self.api, arguments, response) if user is None: return else: forbidden(response) return user.link(self._address) def on_put(self, request, response): """Set or replace the addresses's user.""" if self._user: self._user.unlink(self._address) # Process post data and check for an existing user. fields = CREATION_FIELDS.copy() fields['user_id'] = self.api.to_uuid fields['_optional'] = fields['_optional'] + ( 'user_id', 'email', 'is_server_owner') try: validator = Validator(**fields) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return user_manager = getUtility(IUserManager) if 'user_id' in arguments: user_id = arguments['user_id'] user = user_manager.get_user_by_id(user_id) if user is None: not_found(response, b'No user with ID {}'.format(user_id)) return okay(response) else: user = create_user(self.api, arguments, response) if user is None: return user.link(self._address) @public class Login: """/users//login""" def __init__(self, user): assert user is not None self._user = user def on_post(self, request, response): # We do not want to encrypt the plaintext password given in the POST # data. That would hash the password, but we need to have the # plaintext in order to pass into passlib. validator = Validator(cleartext_password=GetterSetter(str)) try: values = validator(request) except ValueError as error: bad_request(response, str(error)) return is_valid, new_hash = config.password_context.verify( values['cleartext_password'], self._user.password) if is_valid: if new_hash is not None: self._user.password = new_hash no_content(response) else: forbidden(response) @public class OwnersForDomain(_UserBase): """Owners for a particular domain.""" def __init__(self, domain): self._domain = domain def on_get(self, request, response): """/domains//owners""" if self._domain is None: not_found(response) return resource = self._make_collection(request) okay(response, etag(resource)) def on_post(self, request, response): """POST to /domains//owners """ if self._domain is None: not_found(response) return validator = Validator( owner=ListOfDomainOwners(list_of_strings_validator)) try: validator.update(self._domain, request) except ValueError as error: bad_request(response, str(error)) return return no_content(response) def on_delete(self, request, response): """DELETE to /domains//owners""" if self._domain is None: not_found(response) try: # No arguments. Validator()(request) except ValueError as error: bad_request(response, str(error)) return owner_email = [ owner.addresses[0].email for owner in self._domain.owners ] for email in owner_email: self._domain.remove_owner(email) return no_content(response) def _get_collection(self, request): """See `CollectionMixin`.""" return list(self._domain.owners) @public class ServerOwners(_UserBase): """All server owners.""" def on_get(self, request, response): """/owners""" resource = self._make_collection(request) okay(response, etag(resource)) def _get_collection(self, request): """See `CollectionMixin`.""" return list(getUtility(IUserManager).server_owners) mailman-3.1.1/src/mailman/rest/domains.py0000664000175000017500000001351313066532160021445 0ustar maxkingmaxking00000000000000# Copyright (C) 2010-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """REST for domains.""" from mailman.interfaces.domain import ( BadDomainSpecificationError, IDomainManager) from mailman.rest.helpers import ( BadRequest, CollectionMixin, GetterSetter, NotFound, bad_request, child, created, etag, no_content, not_found, okay) from mailman.rest.lists import ListsForDomain from mailman.rest.uris import ADomainURI, AllDomainURIs from mailman.rest.users import ListOfDomainOwners, OwnersForDomain from mailman.rest.validator import Validator, list_of_strings_validator from public import public from zope.component import getUtility class _DomainBase(CollectionMixin): """Shared base class for domain representations.""" def _resource_as_dict(self, domain): """See `CollectionMixin`.""" return dict( description=domain.description, mail_host=domain.mail_host, self_link=self.api.path_to('domains/{}'.format(domain.mail_host)), ) def _get_collection(self, request): """See `CollectionMixin`.""" return list(getUtility(IDomainManager)) @public class ADomain(_DomainBase): """A domain.""" def __init__(self, domain): self._domain = domain def on_get(self, request, response): """Return a single domain end-point.""" domain = getUtility(IDomainManager).get(self._domain) if domain is None: not_found(response) else: okay(response, self._resource_as_json(domain)) def on_delete(self, request, response): """Delete the domain.""" try: getUtility(IDomainManager).remove(self._domain) except KeyError: # The domain does not exist. not_found(response) else: no_content(response) def patch_put(self, request, response, is_optional): domain = getUtility(IDomainManager).get(self._domain) if domain is None: not_found(response) kws = dict( description=GetterSetter(str), owner=ListOfDomainOwners(list_of_strings_validator), ) if is_optional: # For a PATCH, all attributes are optional. kws['_optional'] = kws.keys() try: Validator(**kws).update(domain, request) except ValueError as error: bad_request(response, str(error)) else: no_content(response) def on_put(self, request, response): """Update all the domain except mail_host""" self.patch_put(request, response, is_optional=False) def on_patch(self, request, response): """Patch some domain attributes.""" self.patch_put(request, response, is_optional=True) @child() def lists(self, context, segments): """/domains//lists""" if len(segments) == 0: domain = getUtility(IDomainManager).get(self._domain) if domain is None: return NotFound() return ListsForDomain(domain) else: return BadRequest(), [] @child() def owners(self, context, segments): """/domains//owners""" if len(segments) == 0: domain = getUtility(IDomainManager).get(self._domain) if domain is None: return NotFound() return OwnersForDomain(domain) else: return NotFound(), [] @child() def uris(self, context, segments): """Return the template URIs of the domain. These are only available after API 3.0. """ domain = getUtility(IDomainManager).get(self._domain) if domain is None or self.api.version_info < (3, 1): return NotFound(), [] if len(segments) == 0: return AllDomainURIs(domain) if len(segments) > 1: return BadRequest(), [] template = segments[0] if template not in AllDomainURIs.URIs: return NotFound(), [] return ADomainURI(domain, template), [] @public class AllDomains(_DomainBase): """The domains.""" def on_post(self, request, response): """Create a new domain.""" domain_manager = getUtility(IDomainManager) try: validator = Validator(mail_host=str, description=str, owner=list_of_strings_validator, _optional=('description', 'owner')) values = validator(request) # For consistency, owners are passed in as multiple `owner` keys, # but .add() requires an `owners` keyword. Match impedence. owners = values.pop('owner', None) if owners is not None: values['owners'] = owners domain = domain_manager.add(**values) except BadDomainSpecificationError as error: bad_request(response, str(error)) else: location = self.api.path_to('domains/{}'.format(domain.mail_host)) created(response, location) def on_get(self, request, response): """/domains""" resource = self._make_collection(request) okay(response, etag(resource)) mailman-3.1.1/src/mailman/rest/wsgiapp.py0000664000175000017500000002220313066532160021461 0ustar maxkingmaxking00000000000000# Copyright (C) 2010-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """Basic WSGI Application object for REST server.""" import re import logging from base64 import b64decode from falcon import API, HTTPUnauthorized from falcon.routing import create_http_method_map from mailman.config import config from mailman.database.transaction import transactional from mailman.rest.root import Root from public import public from wsgiref.simple_server import ( WSGIRequestHandler, WSGIServer, make_server as wsgi_server) log = logging.getLogger('mailman.http') MISSING = object() SLASH = '/' EMPTYSTRING = '' REALM = 'mailman3-rest' class AdminWSGIServer(WSGIServer): """Server class that integrates error handling with our log files.""" def handle_error(self, request, client_address): # Interpose base class method so that the exception gets printed to # our log file rather than stderr. log.exception('REST server exception during request from %s', client_address) class StderrLogger: def __init__(self): self._buffer = [] def write(self, message): self._buffer.append(message) def flush(self): self._buffer.insert(0, 'REST request handler error:\n') log.error(EMPTYSTRING.join(self._buffer)) self._buffer = [] class AdminWebServiceWSGIRequestHandler(WSGIRequestHandler): """Handler class which just logs output to the right place.""" default_request_version = 'HTTP/1.1' def log_message(self, format, *args): """See `BaseHTTPRequestHandler`.""" log.info('%s - - %s', self.address_string(), format % args) def get_stderr(self): # Return a fake stderr object that will actually write its output to # the log file. return StderrLogger() class Middleware: """Falcon middleware object for Mailman's REST API. This does two things. It sets the API version on the resource object, and it verifies that the proper authentication has been performed. """ def process_resource(self, request, response, resource, params): # Check the authorization credentials. authorized = False if request.auth is not None and request.auth.startswith('Basic '): # b64decode() returns bytes, but we require a str. credentials = b64decode(request.auth[6:]).decode('utf-8') username, password = credentials.split(':', 1) if (username == config.webservice.admin_user and password == config.webservice.admin_pass): authorized = True if not authorized: # Not authorized. raise HTTPUnauthorized( '401 Unauthorized', 'REST API authorization failed', challenges=['Basic realm=Mailman3']) class ObjectRouter: def __init__(self, root): self._root = root def add_route(self, uri_template, method_map, resource): # We don't need this method for object-based routing. raise NotImplementedError def find(self, uri): segments = uri.split(SLASH) # Since the path is always rooted at /, skip the first segment, which # will always be the empty string. segments.pop(0) this_segment = segments.pop(0) resource = self._root context = {} while True: # Plumb the API through to all child resources. api = getattr(resource, 'api', None) # See if any of the resource's child links match the next segment. for name in dir(resource): if name.startswith('__') and name.endswith('__'): continue attribute = getattr(resource, name, MISSING) assert attribute is not MISSING, name matcher = getattr(attribute, '__matcher__', MISSING) if matcher is MISSING: continue result = None if isinstance(matcher, str): # Is the matcher string a regular expression or plain # string? If it starts with a caret, it's a regexp. if matcher.startswith('^'): cre = re.compile(matcher) # Search against the entire remaining path. tmp_segments = segments[:] tmp_segments.insert(0, this_segment) remaining_path = SLASH.join(tmp_segments) mo = cre.match(remaining_path) if mo: result = attribute( context, segments, **mo.groupdict()) elif matcher == this_segment: result = attribute(context, segments) else: # The matcher is a callable. It returns None if it # doesn't match, and if it does, it returns a 3-tuple # containing the positional arguments, the keyword # arguments, and the remaining segments. The attribute is # then called with these arguments. Note that the matcher # wants to see the full remaining path components, which # includes the current hop. tmp_segments = segments[:] tmp_segments.insert(0, this_segment) matcher_result = matcher(tmp_segments) if matcher_result is not None: positional, keyword, segments = matcher_result result = attribute( context, segments, *positional, **keyword) # The attribute could return a 2-tuple giving the resource and # remaining path segments, or it could just return the result. # Of course, if the result is None, then the matcher did not # match. if result is None: continue elif isinstance(result, tuple): resource, segments = result else: resource = result # See if the context set an API and set it on the next # resource in the chain, falling back to the parent resource's # API if there is one. resource.api = context.pop('api', api) # The method could have truncated the remaining segments, # meaning, it's consumed all the path segments, or this is the # last path segment. In that case the resource we're left at # is the responder. if len(segments) == 0: # We're at the end of the path, so the root must be the # responder. method_map = create_http_method_map(resource) return resource, method_map, context this_segment = segments.pop(0) break else: # None of the attributes matched this path component, so the # response is a 404. return None, None, None class RootedAPI(API): def __init__(self, root, *args, **kws): super().__init__( *args, middleware=Middleware(), router=ObjectRouter(root), **kws) # Let Falcon parse the form data into the request object's # .params attribute. self.req_options.auto_parse_form_urlencoded = True # Don't ignore empty query parameters, e.g. preserve empty string # values, which some resources will interpret as a DELETE. self.req_options.keep_blank_qs_values = True # Override the base class implementation to wrap a transactional # handler around the call, so that the current transaction is # committed if no errors occur, and aborted otherwise. @transactional def __call__(self, environ, start_response): return super().__call__(environ, start_response) @public def make_application(): """Return a callable WSGI application object.""" return RootedAPI(Root()) @public def make_server(): """Create the Mailman REST server. Use this if you just want to run Mailman's wsgiref-based REST server. """ host = config.webservice.hostname port = int(config.webservice.port) server = wsgi_server( host, port, make_application(), server_class=AdminWSGIServer, handler_class=AdminWebServiceWSGIRequestHandler) return server mailman-3.1.1/src/mailman/rest/root.py0000664000175000017500000002544313203705633021003 0ustar maxkingmaxking00000000000000# Copyright (C) 2010-2017 by the Free Software Foundation, Inc. # # This file is part of GNU Mailman. # # GNU Mailman is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) # any later version. # # GNU Mailman is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see . """The root of the REST API.""" from mailman.config import config from mailman.core.api import API30, API31 from mailman.core.constants import system_preferences from mailman.core.system import system from mailman.interfaces.listmanager import IListManager from mailman.model.uid import UID from mailman.rest.addresses import AllAddresses, AnAddress from mailman.rest.bans import BannedEmail, BannedEmails from mailman.rest.domains import ADomain, AllDomains from mailman.rest.helpers import ( BadRequest, NotFound, child, etag, no_content, not_found, okay) from mailman.rest.lists import AList, AllLists, Styles from mailman.rest.members import AMember, AllMembers, FindMembers from mailman.rest.preferences import ReadOnlyPreferences from mailman.rest.queues import AQueue, AQueueFile, AllQueues from mailman.rest.templates import TemplateFinder from mailman.rest.uris import ASiteURI, AllSiteURIs from mailman.rest.users import AUser, AllUsers, ServerOwners from public import public from zope.component import getUtility SLASH = '/' @public class Root: """The RESTful root resource. At the root of the tree are the API version numbers. Everything else lives underneath those. Currently there is only one API version number, and we start at 3.0 to match the Mailman version number. That may not always be the case though. """ @child('3.0') def api_version_30(self, context, segments): # API version 3.0 was introduced in Mailman 3.0. context['api'] = API30 return TopLevel() @child('3.1') def api_version_31(self, context, segments): # API version 3.1 was introduced in Mailman 3.1. Primary backward # incompatible difference is that uuids are represented as hex strings # instead of 128 bit integers. The latter is not compatible with all # versions of JavaScript. context['api'] = API31 return TopLevel() @public class Versions: def on_get(self, request, response): """//system/versions""" resource = dict( mailman_version=system.mailman_version, python_version=system.python_version, api_version=self.api.version, self_link=self.api.path_to('system/versions'), ) okay(response, etag(resource)) @public class SystemConfiguration: def __init__(self, section=None): self._section = section def on_get(self, request, response): if self._section is None: resource = dict( sections=sorted(section.name for section in config), self_link=self.api.path_to('system/configuration'), ) okay(response, etag(resource)) return missing = object() section = getattr(config, self._section, missing) if section is missing: not_found(response) return # Sections don't have .keys(), .values(), or .items() but we can # iterate over them. resource = {key: section[key] for key in section} # Add a `self_link` attribute to the resource. This is a little ugly # because technically speaking we're mixing namespaces. We can't have # a variable named `self_link` in any section, but also we can't have # `http_etag` either, so unless we want to shove all these values into # a sub dictionary (which we don't), we have to live with it. self_link = self.api.path_to( 'system/configuration/{}'.format(section.name)) resource['self_link'] = self_link okay(response, etag(resource)) @public class Pipelines: def on_get(self, request, response): resource = dict(pipelines=sorted(config.pipelines)) okay(response, etag(resource)) @public class Chains: def on_get(self, request, response): resource = dict(chains=sorted(config.chains)) okay(response, etag(resource)) @public class Reserved: """Top level API for reserved operations. Nothing under this resource should be considered part of the stable API. The resources that appear here are purely for the support of external non-production systems, such as testing infrastructures for cooperating components. Use at your own risk. """ def __init__(self, segments): self._resource_path = SLASH.join(segments) def on_delete(self, request, response): if self._resource_path != 'uids/orphans': not_found(response) return UID.cull_orphans() no_content(response) @public class TopLevel: """Top level collections and entries.""" @child() def system(self, context, segments): """//system""" if len(segments) == 0: # This provides backward compatibility; see /system/versions. return Versions() elif segments[0] == 'preferences': if len(segments) > 1: return BadRequest(), [] return ReadOnlyPreferences(system_preferences, 'system'), [] elif segments[0] == 'versions': if len(segments) > 1: return BadRequest(), [] return Versions(), [] elif segments[0] == 'configuration': if len(segments) <= 2: return SystemConfiguration(*segments[1:]), [] return BadRequest(), [] elif segments[0] == 'pipelines': if len(segments) > 1: return BadRequest(), [] return Pipelines(), [] elif segments[0] == 'chains': if len(segments) > 1: return BadRequest(), [] return Chains(), [] else: return NotFound(), [] @child() def addresses(self, context, segments): """//addresses //addresses/ """ if len(segments) == 0: return AllAddresses() else: email = segments.pop(0) return AnAddress(email), segments @child() def domains(self, context, segments): """//domains //domains/ """ if len(segments) == 0: return AllDomains() else: domain = segments.pop(0) return ADomain(domain), segments @child() def lists(self, context, segments): """//lists //lists/styles //lists/ //lists//... """ if len(segments) == 0: return AllLists() # This does not prevent a mailing list being created with a short name # 'styles', since list identifiers (see below) must either be a # List-Id like styles.example.com, or an fqdn_listname like # styles@example.com. elif len(segments) == 1 and segments[0] == 'styles': return Styles(), [] else: # list-id is preferred, but for backward compatibility, # fqdn_listname is also accepted. list_identifier = segments.pop(0) return AList(list_identifier), segments @child() def members(self, context, segments): """//members""" if len(segments) == 0: return AllMembers() # Either the next segment is the string "find" or a member id. They # cannot collide. segment = segments.pop(0) if segment == 'find': resource = FindMembers() else: try: member_id = self.api.to_uuid(segment) except ValueError: member_id = None resource = AMember(member_id) return resource, segments @child() def users(self, context, segments): """//users""" if len(segments) == 0: return AllUsers() else: user_identifier = segments.pop(0) return AUser(user_identifier), segments @child() def owners(self, context, segments): """//owners""" if len(segments) != 0: return BadRequest(), [] else: return ServerOwners(), segments @child() def templates(self, context, segments): """//templates//