Description: Upstream changes introduced in version 0.3b3 This patch has been created by dpkg-source during the package build. Here's the last changelog entry, hopefully it gives details on why those changes were made: . jmc (0.3b3) unstable; urgency=low . * JMC version 0.3 beta 3 . The person named in the Author field signed this changelog entry. Author: David Rousselie --- The information above should follow the Patch Tagging Guidelines, please checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here are templates for supplementary fields that you might want to add: Origin: , Bug: Bug-Debian: http://bugs.debian.org/ Forwarded: Reviewed-By: Last-Update: --- /dev/null +++ jmc-0.3b3/jmc-local.conf @@ -0,0 +1,45 @@ +[jabber] +server: localhost +port: 5275 +secret: secret +service_jid: jmc.octo-dro-linux +#supported language: en, fr (See src/jmc/lang.py to add more) +language: en + +[db] +#SQLite config +type: sqlite +host: +name: /tmp/jmc.db +#Mysql config +#type: mysql +#host: root:pass@localhost +#name: /jmc +#db_url: %(type)s://%(host)s%(name)s?debug=1&debugThreading=1 +db_url: %(type)s://%(host)s%(name)s + + +[component] +pid_file: /tmp/jmc.pid +#motd: "Message of the day" +welcome_message: "Welcome to Jabber Mail Component" +# a comma separated list of JIDs +admins: admin@localhost +log_file: /tmp/jmc.log + +[jmc] +mail_default_encoding: iso-8859-1 +check_interval: 1 + +[vcard] +url: http://people.happycoders.org/dax/projects/jmc + +[smtp] +smtp_default_login: test +smtp_default_password: test +smtp_default_host: testhost +smtp_default_port: 25 +smtp_default_tls: True +smtp_default_label: Default SMTP Server +enable_smtp_default_account: False + --- /dev/null +++ jmc-0.3b3/Makefile @@ -0,0 +1,32 @@ +PYTHON=`which python` +DESTDIR=/ +BUILDIR=$(CURDIR)/debian/jmc +PROJECT=jmc +VERSION=0.3b3 + +all: + @echo "make source - Create source package" + @echo "make install - Install on local system" + @echo "make buildrpm - Generate a rpm package" + @echo "make builddeb - Generate a deb package" + @echo "make clean - Get rid of scratch and byte files" + +source: + $(PYTHON) setup.py sdist $(COMPILE) + +install: + $(PYTHON) setup.py install --root $(DESTDIR) $(COMPILE) + +buildrpm: + $(PYTHON) setup.py bdist_rpm --post-install=rpm/postinstall --pre-uninstall=rpm/preuninstall + +builddeb: + $(PYTHON) setup.py sdist $(COMPILE) --dist-dir=../ + rename -f 's/$(PROJECT)-(.*)\.tar\.gz/$(PROJECT)_$$1\.orig\.tar\.gz/' ../* + dpkg-buildpackage -us -uc -i -I -rfakeroot + +clean: + $(PYTHON) setup.py clean + fakeroot $(MAKE) -f $(CURDIR)/debian/rules clean + rm -rf build/ MANIFEST + find . -name '*.pyc' -delete --- /dev/null +++ jmc-0.3b3/analyse_profiling.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +## +## analyse_profiling.py +## Login : David Rousselie +## Started on Thu May 29 19:09:02 2008 David Rousselie +## $Id$ +## +## Copyright (C) 2008 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import pstats + +stats = pstats.Stats("jmc.prof") +stats.strip_dirs().sort_stats('time').print_stats() --- /dev/null +++ jmc-0.3b3/run_tests.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +## +## run_tests.py +## Login : David Rousselie +## Started on Wed Aug 9 21:37:35 2006 David Rousselie +## $Id$ +## +## Copyright (C) 2006 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import coverage +coverage.erase() +coverage.start() + +import logging +import unittest +from test import test_support + +import sys +sys.path.append("src") +reload(sys) +sys.setdefaultencoding('utf8') +del sys.setdefaultencoding + +import jmc +import jmc.jabber +import jmc.jabber.component + +import jmc.tests + +def suite(): + return jmc.tests.suite() + +if __name__ == '__main__': + class MyTestProgram(unittest.TestProgram): + def runTests(self): + """run tests but do not exit after""" + self.testRunner = unittest.TextTestRunner(verbosity=self.verbosity) + self.testRunner.run(self.test) + + logger = logging.getLogger() + logger.addHandler(logging.StreamHandler()) + logger.setLevel(logging.CRITICAL) + + MyTestProgram(defaultTest='suite') + +coverage.report(["src/jmc/__init__.py", + "src/jmc/lang.py", + "src/jmc/runner.py", + "src/jmc/jabber/__init__.py", + "src/jmc/jabber/command.py", + "src/jmc/jabber/component.py", + "src/jmc/jabber/disco.py", + "src/jmc/jabber/message.py", + "src/jmc/jabber/presence.py", + "src/jmc/jabber/presence.py", + "src/jmc/model/__init__.py", + "src/jmc/model/account.py"]) --- /dev/null +++ jmc-0.3b3/profile_jmc.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +## +## profile_jmc.py +## Login : David Rousselie +## Started on Thu May 29 19:09:02 2008 David Rousselie +## $Id$ +## +## Copyright (C) 2008 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import cProfile +import jmc.runner as runner + +cProfile.run("runner.main()", "jmc.prof") --- /dev/null +++ jmc-0.3b3/resolv.conf @@ -0,0 +1,2 @@ +# Generated by NetworkManager +nameserver 192.168.10.110 --- /dev/null +++ jmc-0.3b3/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. --- /dev/null +++ jmc-0.3b3/TODO @@ -0,0 +1,12 @@ +* Support for attachements with size limit and file format limit + (e.g. only png, jpeg,... but no exe, bat,...). + +* Make real documentation + +* Support for Ad Hoc Commands (see PyMSNt cvs, avatar + branch). Interesting for statistics. + +* Support for epoll, kpoll and kqueu (see PyMSNt cvs, avatar branch + code). + + --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-11-05/POP3Account_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2007-11-05T19:02:34 +-- Class jmc.model.account.POP3Account +-- Database: sqlite +CREATE TABLE po_p3_account ( + id INTEGER PRIMARY KEY, + nb_mail INT, + lastmail INT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-11-05/PresenceAccount_sqlite.sql @@ -0,0 +1,13 @@ +-- Exported definition from 2007-11-05T19:02:34 +-- Class jcl.model.account.PresenceAccount +-- Database: sqlite +CREATE TABLE presence_account ( + id INTEGER PRIMARY KEY, + chat_action INT, + online_action INT, + away_action INT, + xa_action INT, + dnd_action INT, + offline_action INT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-11-05/IMAPAccount_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2007-11-05T19:02:34 +-- Class jmc.model.account.IMAPAccount +-- Database: sqlite +CREATE TABLE imap_account ( + id INTEGER PRIMARY KEY, + mailbox TEXT, + delimiter TEXT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-11-05/User_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2007-11-05T19:02:34 +-- Class jcl.model.account.User +-- Database: sqlite +CREATE TABLE user ( + id INTEGER PRIMARY KEY, + jid TEXT, + has_received_motd TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-11-05/LegacyJID_sqlite.sql @@ -0,0 +1,10 @@ +-- Exported definition from 2007-11-05T19:02:34 +-- Class jcl.model.account.LegacyJID +-- Database: sqlite +CREATE TABLE legacy_j_id ( + id INTEGER PRIMARY KEY, + legacy_address TEXT, + jid TEXT, + account_id INT CONSTRAINT account_id_exists REFERENCES account(id) , + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-11-05/SMTPAccount_sqlite.sql @@ -0,0 +1,16 @@ +-- Exported definition from 2007-11-05T19:02:34 +-- Class jmc.model.account.SMTPAccount +-- Database: sqlite +CREATE TABLE smtp_account ( + id INTEGER PRIMARY KEY, + login TEXT, + password TEXT, + host TEXT, + port INT, + tls TINYINT, + store_password TINYINT, + waiting_password_reply TINYINT, + default_from TEXT, + default_account TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-11-05/MailAccount_sqlite.sql @@ -0,0 +1,18 @@ +-- Exported definition from 2007-11-05T19:02:34 +-- Class jmc.model.account.MailAccount +-- Database: sqlite +CREATE TABLE mail_account ( + id INTEGER PRIMARY KEY, + login TEXT, + password TEXT, + host TEXT, + port INT, + _ssl TINYINT, + _interval INT, + store_password TINYINT, + live_email_only TINYINT, + lastcheck INT, + waiting_password_reply TINYINT, + first_check TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-11-05/Account_sqlite.sql @@ -0,0 +1,14 @@ +-- Exported definition from 2007-11-05T19:02:34 +-- Class jcl.model.account.Account +-- Database: sqlite +CREATE TABLE account ( + id INTEGER PRIMARY KEY, + name TEXT, + jid TEXT, + status TEXT, + in_error TINYINT, + enabled TINYINT, + lastlogin TIMESTAMP, + user_id INT CONSTRAINT user_id_exists REFERENCES user(id) , + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2008-05-29/POP3Account_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2008-05-29T19:26:03 +-- Class jmc.model.account.POP3Account +-- Database: sqlite +CREATE TABLE po_p3_account ( + id INTEGER PRIMARY KEY, + nb_mail INT, + lastmail INT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2008-05-29/IMAPAccount_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2008-05-29T19:26:03 +-- Class jmc.model.account.IMAPAccount +-- Database: sqlite +CREATE TABLE imap_account ( + id INTEGER PRIMARY KEY, + mailbox TEXT, + delimiter TEXT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2008-05-29/SMTPAccount_sqlite.sql @@ -0,0 +1,7 @@ +-- Exported definition from 2008-05-29T19:26:03 +-- Class jmc.model.account.SMTPAccount +-- Database: sqlite +CREATE TABLE smtp_account ( + id INTEGER PRIMARY KEY, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2008-05-29/MailAccount_sqlite.sql @@ -0,0 +1,18 @@ +-- Exported definition from 2008-05-29T19:26:03 +-- Class jmc.model.account.MailAccount +-- Database: sqlite +CREATE TABLE mail_account ( + id INTEGER PRIMARY KEY, + login TEXT, + password TEXT, + host TEXT, + port INT, + _ssl TINYINT, + _interval INT, + store_password TINYINT, + live_email_only TINYINT, + lastcheck INT, + waiting_password_reply TINYINT, + first_check TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2008-05-29/AbstractSMTPAccount_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2008-05-29T19:26:03 +-- Class jmc.model.account.AbstractSMTPAccount +-- Database: sqlite +CREATE TABLE abstract_smtp_account ( + id INTEGER PRIMARY KEY, + default_from TEXT, + default_account TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2008-05-29/GlobalSMTPAccount_sqlite.sql @@ -0,0 +1,14 @@ +-- Exported definition from 2008-05-29T19:26:03 +-- Class jmc.model.account.GlobalSMTPAccount +-- Database: sqlite +CREATE TABLE global_smtp_account ( + id INTEGER PRIMARY KEY, + login TEXT, + password TEXT, + host TEXT, + port INT, + tls TINYINT, + store_password TINYINT, + waiting_password_reply TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/POP3Account_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2007-12-04T17:57:39 +-- Class jmc.model.account.POP3Account +-- Database: sqlite +CREATE TABLE po_p3_account ( + id INTEGER PRIMARY KEY, + nb_mail INT, + lastmail INT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/PresenceAccount_sqlite.sql @@ -0,0 +1,13 @@ +-- Exported definition from 2007-12-04T17:57:39 +-- Class jcl.model.account.PresenceAccount +-- Database: sqlite +CREATE TABLE presence_account ( + id INTEGER PRIMARY KEY, + chat_action INT, + online_action INT, + away_action INT, + xa_action INT, + dnd_action INT, + offline_action INT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/upgrade_sqlite_2008-05-29.sql @@ -0,0 +1,66 @@ +-- Class jmc.model.account.AbstractSMTPAccount +-- Database: sqlite +CREATE TABLE abstract_smtp_account ( + id INTEGER PRIMARY KEY, + default_from TEXT, + default_account TINYINT, + child_name VARCHAR(255) +); + +-- Class jmc.model.account.GlobalSMTPAccount +-- Database: sqlite +CREATE TABLE global_smtp_account ( + id INTEGER PRIMARY KEY, + login TEXT, + password TEXT, + host TEXT, + port INT, + tls TINYINT, + store_password TINYINT, + waiting_password_reply TINYINT, + child_name VARCHAR(255) +); + +INSERT INTO abstract_smtp_account + SELECT + id, + default_from, + default_account, + "GlobalSMTPAccount" + FROM + smtp_account; + +INSERT INTO global_smtp_account + SELECT + id, + login, + password, + host, + port, + tls, + store_password, + waiting_password_reply, + "SMTPAccount" + FROM + smtp_account; + +DROP TABLE smtp_account; + +-- Class jmc.model.account.SMTPAccount +-- Database: sqlite +CREATE TABLE smtp_account ( + id INTEGER PRIMARY KEY, + child_name VARCHAR(255) +); + +INSERT INTO smtp_account + SELECT + id, + NULL + FROM + global_smtp_account; + +UPDATE account SET + child_name="AbstractSMTPAccount" +WHERE + child_name="SMTPAccount"; --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/IMAPAccount_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2007-12-04T17:57:39 +-- Class jmc.model.account.IMAPAccount +-- Database: sqlite +CREATE TABLE imap_account ( + id INTEGER PRIMARY KEY, + mailbox TEXT, + delimiter TEXT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/User_sqlite.sql @@ -0,0 +1,9 @@ +-- Exported definition from 2007-12-04T17:57:39 +-- Class jcl.model.account.User +-- Database: sqlite +CREATE TABLE user ( + id INTEGER PRIMARY KEY, + jid TEXT, + has_received_motd TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/LegacyJID_sqlite.sql @@ -0,0 +1,10 @@ +-- Exported definition from 2007-12-04T17:57:39 +-- Class jcl.model.account.LegacyJID +-- Database: sqlite +CREATE TABLE legacy_j_id ( + id INTEGER PRIMARY KEY, + legacy_address TEXT, + jid TEXT, + account_id INT CONSTRAINT account_id_exists REFERENCES account(id) , + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/SMTPAccount_sqlite.sql @@ -0,0 +1,16 @@ +-- Exported definition from 2007-12-04T17:57:39 +-- Class jmc.model.account.SMTPAccount +-- Database: sqlite +CREATE TABLE smtp_account ( + id INTEGER PRIMARY KEY, + login TEXT, + password TEXT, + host TEXT, + port INT, + tls TINYINT, + store_password TINYINT, + waiting_password_reply TINYINT, + default_from TEXT, + default_account TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/MailAccount_sqlite.sql @@ -0,0 +1,18 @@ +-- Exported definition from 2007-12-04T17:57:39 +-- Class jmc.model.account.MailAccount +-- Database: sqlite +CREATE TABLE mail_account ( + id INTEGER PRIMARY KEY, + login TEXT, + password TEXT, + host TEXT, + port INT, + _ssl TINYINT, + _interval INT, + store_password TINYINT, + live_email_only TINYINT, + lastcheck INT, + waiting_password_reply TINYINT, + first_check TINYINT, + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/sqlobject_history/2007-12-04/Account_sqlite.sql @@ -0,0 +1,14 @@ +-- Exported definition from 2007-12-04T17:57:39 +-- Class jcl.model.account.Account +-- Database: sqlite +CREATE TABLE account ( + id INTEGER PRIMARY KEY, + name TEXT, + jid TEXT, + status TEXT, + error TEXT, + enabled TINYINT, + lastlogin TIMESTAMP, + user_id INT CONSTRAINT user_id_exists REFERENCES user(id) , + child_name VARCHAR(255) +) --- /dev/null +++ jmc-0.3b3/conf/jmc.conf @@ -0,0 +1,45 @@ +[jabber] +server: localhost +port: 5347 +secret: secret +service_jid: jmc.localhost +#supported language: en, fr (See src/jmc/lang.py to add more) +language: en + +[db] +#SQLite config +type: sqlite +host: +name: /var/spool/jabber/jmc.db +#Mysql config +#type: mysql +#host: root:pass@localhost +#name: /jmc +#db_url: %(type)s://%(host)s%(name)s?debug=1&debugThreading=1 +db_url: %(type)s://%(host)s%(name)s + + +[component] +pid_file: /var/run/jabber/jmc.pid +#motd: "Message of the day" +welcome_message: "Welcome to Jabber Mail Component" +# a comma separated list of JIDs +admins: admin@localhost +log_file: /var/log/jabber/jmc.log + +[jmc] +mail_default_encoding: iso-8859-1 +check_interval: 1 + +[vcard] +url: http://people.happycoders.org/dax/projects/jmc + +[smtp] +smtp_default_login: test +smtp_default_password: test +smtp_default_host: testhost +smtp_default_port: 25 +smtp_default_tls: True +smtp_default_label: Default SMTP Server +enable_smtp_default_account: False + --- /dev/null +++ jmc-0.3b3/src/jmc/tests/runner.py @@ -0,0 +1,324 @@ +## +## runner.py +## Login : David Rousselie +## Started on Fri May 18 13:43:37 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2007 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import unittest +import sys +import os + +from jcl.tests import JCLTestCase +from jcl.tests.runner import JCLRunner_TestCase + +import jcl.model as model +from jcl.model.account import Account, PresenceAccount, User, LegacyJID + +import jmc +from jmc.lang import Lang +from jmc.runner import JMCRunner +from jmc.jabber.component import MailComponent +import jmc.model.account as account +from jmc.model.account import MailAccount, IMAPAccount, POP3Account, \ + AbstractSMTPAccount, GlobalSMTPAccount, SMTPAccount + +if sys.platform == "win32": + DB_PATH = "/c|/temp/test.db" +else: + DB_PATH = "/tmp/test.db" +DB_URL = "sqlite://" + DB_PATH# + "?debug=1&debugThreading=1" + +class JMCRunner_TestCase(JCLTestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[Account, PresenceAccount, User, + GlobalSMTPAccount, AbstractSMTPAccount]) + self.runner = JMCRunner("Jabber Mail Component", jmc.version) + self.smtp_default_login = account.smtp_default_login + self.smtp_default_password = account.smtp_default_password + self.smtp_default_host = account.smtp_default_host + self.smtp_default_port = account.smtp_default_port + self.smtp_default_tls = account.smtp_default_tls + self.mail_default_encoding = MailAccount.default_encoding + self.type_globalsmtp_name = Lang.en.type_globalsmtp_name + + def tearDown(self): + self.runner = None + sys.argv = [""] + account.smtp_default_login = self.smtp_default_login + account.smtp_default_password = self.smtp_default_password + account.smtp_default_host = self.smtp_default_host + account.smtp_default_port = self.smtp_default_port + account.smtp_default_tls = self.smtp_default_tls + MailAccount.default_encoding = self.mail_default_encoding + Lang.en.type_globalsmtp_name = self.type_globalsmtp_name + + def test_configure_default(self): + self.runner.configure() + self.assertEquals(self.runner.config_file, "jmc.conf") + self.assertEquals(self.runner.server, "localhost") + self.assertEquals(self.runner.port, 5347) + self.assertEquals(self.runner.secret, "secret") + self.assertEquals(self.runner.service_jid, "jmc.localhost") + self.assertEquals(self.runner.language, "en") + self.assertEquals(self.runner.db_url, "sqlite:///var/spool/jabber/jmc.db") + self.assertEquals(self.runner.pid_file, "/var/run/jabber/jmc.pid") + self.assertFalse(self.runner.debug) + self.assertEquals(self.runner.mail_default_encoding, "iso-8859-1") + self.assertEquals(self.runner.smtp_default_login, None) + self.assertEquals(self.runner.smtp_default_password, None) + self.assertEquals(self.runner.smtp_default_host, None) + self.assertEquals(self.runner.smtp_default_port, 0) + self.assertEquals(self.runner.smtp_default_tls, False) + self.assertEquals(self.runner.enable_smtp_default_account, False) + self.assertEquals(self.runner.smtp_default_label, None) + self.runner.setup_smtp_default() + self.assertEquals(Lang.en.type_globalsmtp_name, + "Default SMTP Server") + _account = GlobalSMTPAccount(user=User(jid="user1@test.com"), + name="account1", + jid="account1@jmc.test.com") + self.assertEquals(_account.login, '') + self.assertEquals(_account.password, '') + self.assertEquals(_account.host, 'localhost') + self.assertEquals(_account.port, 25) + self.assertEquals(_account.tls, False) + + def test_configure_configfile(self): + self.runner.config_file = "src/jmc/tests/jmc.conf" + self.runner.configure() + self.assertEquals(self.runner.server, "test_localhost") + self.assertEquals(self.runner.port, 42) + self.assertEquals(self.runner.secret, "test_secret") + self.assertEquals(self.runner.service_jid, "test_jmc.localhost") + self.assertEquals(self.runner.language, "test_en") + self.assertEquals(self.runner.db_url, "test_sqlite://root@localhost/var/spool/jabber/test_jmc.db") + self.assertEquals(self.runner.pid_file, "/var/run/jabber/test_jmc.pid") + self.assertFalse(self.runner.debug) + self.assertEquals(self.runner.mail_default_encoding, "test_iso-8859-1") + self.assertEquals(self.runner.smtp_default_login, "testlogin") + self.assertEquals(self.runner.smtp_default_password, "testpassword") + self.assertEquals(self.runner.smtp_default_host, "testhost") + self.assertEquals(self.runner.smtp_default_port, 2525) + self.assertEquals(self.runner.smtp_default_tls, True) + self.assertEquals(self.runner.enable_smtp_default_account, True) + self.assertEquals(self.runner.smtp_default_label, "SMTP Server") + self.runner.setup_smtp_default() + self.assertEquals(Lang.en.type_globalsmtp_name, + "SMTP Server") + _account = GlobalSMTPAccount(user=User(jid="user1@test.com"), + name="account1", + jid="account1@jmc.test.com") + self.assertEquals(_account.login, 'testlogin') + self.assertEquals(_account.password, 'testpassword') + self.assertEquals(_account.host, 'testhost') + self.assertEquals(_account.port, 2525) + self.assertEquals(_account.tls, True) + + def test_configure_uncomplete_configfile(self): + self.runner.config_file = "src/jmc/tests/uncomplete_jmc.conf" + self.runner.configure() + self.assertEquals(self.runner.server, "test_localhost") + self.assertEquals(self.runner.port, 42) + self.assertEquals(self.runner.secret, "test_secret") + self.assertEquals(self.runner.service_jid, "test_jmc.localhost") + self.assertEquals(self.runner.language, "test_en") + self.assertEquals(self.runner.db_url, "test_sqlite://root@localhost/var/spool/jabber/test_jmc.db") + self.assertEquals(self.runner.pid_file, "/var/run/jabber/test_jmc.pid") + self.assertFalse(self.runner.debug) + self.assertEquals(self.runner.mail_default_encoding, "test_iso-8859-1") + self.assertEquals(self.runner.smtp_default_login, None) + self.assertEquals(self.runner.smtp_default_password, None) + self.assertEquals(self.runner.smtp_default_host, None) + self.assertEquals(self.runner.smtp_default_port, 0) + self.assertEquals(self.runner.smtp_default_tls, False) + self.assertEquals(self.runner.enable_smtp_default_account, False) + self.assertEquals(self.runner.smtp_default_label, None) + self.runner.setup_smtp_default() + self.assertEquals(Lang.en.type_globalsmtp_name, + "Default SMTP Server") + _account = GlobalSMTPAccount(user=User(jid="user1@test.com"), + name="account1", + jid="account1@jmc.test.com") + self.assertEquals(_account.login, '') + self.assertEquals(_account.password, '') + self.assertEquals(_account.host, 'localhost') + self.assertEquals(_account.port, 25) + self.assertEquals(_account.tls, False) + + def test_configure_commandline_shortopt(self): + sys.argv = ["", "-c", "src/jmc/tests/jmc.conf", + "-S", "test2_localhost", + "-P", "43", + "-s", "test2_secret", + "-j", "test2_jmc.localhost", + "-l", "test2_en", + "-u", "sqlite:///tmp/test_jmc.db", + "-p", "/tmp/test_jmc.pid", + "-e", "test2_iso-8859-1", + "-g", "testlogin", + "-a", "testpassword", + "-t", "testhost", + "-r", "2525", + "-m", "True", + "-n", "True", + "-b", "My Global SMTP server"] + self.runner.configure() + self.assertEquals(self.runner.server, "test2_localhost") + self.assertEquals(self.runner.port, 43) + self.assertEquals(self.runner.secret, "test2_secret") + self.assertEquals(self.runner.service_jid, "test2_jmc.localhost") + self.assertEquals(self.runner.language, "test2_en") + self.assertEquals(self.runner.db_url, "sqlite:///tmp/test_jmc.db") + self.assertEquals(self.runner.pid_file, "/tmp/test_jmc.pid") + self.assertFalse(self.runner.debug) + self.assertEquals(self.runner.mail_default_encoding, "test2_iso-8859-1") + self.assertEquals(self.runner.smtp_default_login, "testlogin") + self.assertEquals(self.runner.smtp_default_password, "testpassword") + self.assertEquals(self.runner.smtp_default_host, "testhost") + self.assertEquals(self.runner.smtp_default_port, 2525) + self.assertEquals(self.runner.smtp_default_tls, True) + self.assertEquals(self.runner.enable_smtp_default_account, True) + self.assertEquals(self.runner.smtp_default_label, "My Global SMTP server") + self.runner.setup_smtp_default() + self.assertEquals(Lang.en.type_globalsmtp_name, + "My Global SMTP server") + _account = GlobalSMTPAccount(user=User(jid="user1@test.com"), + name="account1", + jid="account1@jmc.test.com") + self.assertEquals(_account.login, 'testlogin') + self.assertEquals(_account.password, 'testpassword') + self.assertEquals(_account.host, 'testhost') + self.assertEquals(_account.port, 2525) + self.assertEquals(_account.tls, True) + + def test_configure_commandline_longopt(self): + sys.argv = ["", "--config-file", "src/jmc/tests/jmc.conf", + "--server", "test2_localhost", + "--port", "43", + "--secret", "test2_secret", + "--service-jid", "test2_jmc.localhost", + "--language", "test2_en", + "--db-url", "sqlite:///tmp/test_jmc.db", + "--pid-file", "/tmp/test_jmc.pid", + "--mail-default-encoding", "test2_iso-8859-1", + "--smtp-default-login", "testlogin", + "--smtp-default-password", "testpassword", + "--smtp-default-host", "testhost", + "--smtp-default-port", "2525", + "--smtp-default-tls", "True", + "--enable-smtp-default-account", "True", + "--smtp-default-label", "My Global SMTP server"] + self.runner.configure() + self.assertEquals(self.runner.server, "test2_localhost") + self.assertEquals(self.runner.port, 43) + self.assertEquals(self.runner.secret, "test2_secret") + self.assertEquals(self.runner.service_jid, "test2_jmc.localhost") + self.assertEquals(self.runner.language, "test2_en") + self.assertEquals(self.runner.db_url, "sqlite:///tmp/test_jmc.db") + self.assertEquals(self.runner.pid_file, "/tmp/test_jmc.pid") + self.assertFalse(self.runner.debug) + self.assertEquals(self.runner.mail_default_encoding, "test2_iso-8859-1") + self.assertEquals(self.runner.smtp_default_login, "testlogin") + self.assertEquals(self.runner.smtp_default_password, "testpassword") + self.assertEquals(self.runner.smtp_default_host, "testhost") + self.assertEquals(self.runner.smtp_default_port, 2525) + self.assertEquals(self.runner.smtp_default_tls, True) + self.assertEquals(self.runner.enable_smtp_default_account, True) + self.assertEquals(self.runner.smtp_default_label, "My Global SMTP server") + self.runner.setup_smtp_default() + self.assertEquals(Lang.en.type_globalsmtp_name, + "My Global SMTP server") + _account = GlobalSMTPAccount(user=User(jid="user1@test.com"), + name="account1", + jid="account1@jmc.test.com") + self.assertEquals(_account.login, 'testlogin') + self.assertEquals(_account.password, 'testpassword') + self.assertEquals(_account.host, 'testhost') + self.assertEquals(_account.port, 2525) + self.assertEquals(_account.tls, True) + + def test__run(self): + self.runner.pid_file = "/tmp/jmc.pid" + self.runner.db_url = DB_URL + def do_nothing(): + return (False, 0) + self.runner._run(do_nothing) + model.db_connection_str = self.runner.db_url + model.db_connect() + # dropTable should succeed because tables should exist + Account.dropTable() + PresenceAccount.dropTable() + User.dropTable() + LegacyJID.dropTable() + MailAccount.dropTable() + IMAPAccount.dropTable() + POP3Account.dropTable() + SMTPAccount.dropTable() + model.db_disconnect() + os.unlink(DB_PATH) + self.assertFalse(os.access("/tmp/jmc.pid", os.F_OK)) + + def test_run_without_smtp_default_account(self): + """ """ + def run_func(mail_component_self): + """ """ + self.assertEquals(mail_component_self.account_manager.account_classes, + (IMAPAccount, POP3Account, SMTPAccount)) + return (False, 0) + + self.runner.enable_smtp_default_account = False + self.runner.pid_file = "/tmp/jmc.pid" + self.runner.db_url = DB_URL + self.runner.config = None + old_run_func = MailComponent.run + MailComponent.run = run_func + try: + self.runner.run() + finally: + MailComponent.run = old_run_func + self.assertFalse(os.access("/tmp/jmc.pid", os.F_OK)) + + def test_run_with_smtp_default_account(self): + """ """ + def run_func(mail_component_self): + """ """ + self.assertEquals(mail_component_self.account_manager.account_classes, + (IMAPAccount, POP3Account, SMTPAccount, + GlobalSMTPAccount)) + return (False, 0) + + self.runner.enable_smtp_default_account = True + self.runner.pid_file = "/tmp/jmc.pid" + self.runner.db_url = DB_URL + self.runner.config = None + old_run_func = MailComponent.run + MailComponent.run = run_func + try: + self.runner.run() + finally: + MailComponent.run = old_run_func + self.assertFalse(os.access("/tmp/jmc.pid", os.F_OK)) + +def suite(): + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(JMCRunner_TestCase, 'test')) + return test_suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/tests/uncomplete_jmc.conf @@ -0,0 +1,23 @@ +[jabber] +server: test_localhost +port: 42 +secret: test_secret +service_jid: test_jmc.localhost +#supported language: en, fr (See src/jmc/lang.py to add more) +language: test_en + +[db] +#type: mysql +type: test_sqlite +#host: root@localhost +host: root@localhost +name: /var/spool/jabber/test_jmc.db +#url: %(type)%(host)%(name)?debug=1&debugThreading=1 +db_url: %(type)s://%(host)s%(name)s + +[component] +pid_file: /var/run/jabber/test_jmc.pid +log_file: /tmp/jmc.log + +[jmc] +mail_default_encoding: test_iso-8859-1 --- /dev/null +++ jmc-0.3b3/src/jmc/tests/__init__.py @@ -0,0 +1,19 @@ +"""JMC test module""" +__revision__ = "" + +import unittest + +from jmc.tests import lang, runner +from jmc.jabber import tests as jabber +from jmc.model import tests as model + +def suite(): + test_suite = unittest.TestSuite() + test_suite.addTest(lang.suite()) + test_suite.addTest(runner.suite()) + test_suite.addTest(jabber.suite()) + test_suite.addTest(model.suite()) + return test_suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/tests/lang.py @@ -0,0 +1,219 @@ +# -*- coding: utf-8 -*- +## +## test_lang.py +## Login : David Rousselie +## Started on Fri May 20 10:46:58 2005 +## $Id: test_lang.py,v 1.1 2005/07/11 20:39:31 dax Exp $ +## +## Copyright (C) 2005 +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import unittest + +import jcl.tests.lang + +import jmc.lang +from jmc.lang import Lang + +from pyxmpp.iq import Iq + +class Lang_TestCase(unittest.TestCase): + def setUp(self): + self.lang = Lang() + + def tearDown(self): + self.lang = None + + def test_get_lang_class_exist(self): + lang_class = self.lang.get_lang_class("fr") + self.assertEquals(lang_class, Lang.fr) + + def test_get_lang_class_not_exist(self): + lang_class = self.lang.get_lang_class("not_exist") + self.assertEquals(lang_class, Lang.en) + + def test_get_lang_class_long_code(self): + lang_class = self.lang.get_lang_class("fr_FR") + self.assertEquals(lang_class, Lang.fr) + + def test_get_lang_from_node(self): + iq = Iq(from_jid = "test@test.com", \ + to_jid = "test2@test.com", \ + stanza_type = "get") + iq_node = iq.get_node() + iq_node.setLang("fr") + lang = self.lang.get_lang_from_node(iq_node) + self.assertEquals(lang, "fr") + + def test_get_lang_class_from_node(self): + iq = Iq(from_jid = "test@test.com", \ + to_jid = "test2@test.com", \ + stanza_type = "get") + iq_node = iq.get_node() + iq_node.setLang("fr") + lang = self.lang.get_lang_class_from_node(iq_node) + self.assertEquals(lang, Lang.fr) + +class Language_TestCase(jcl.tests.lang.Language_TestCase): + """Test language classes""" + + def setUp(self): + """must define self.lang_class. Lang.en is default""" + self.lang_class = Lang.en + + def test_strings(self): + jcl.tests.lang.Language_TestCase.test_strings(self) + + self.assertNotEquals(self.lang_class.field_login, None) + self.assertNotEquals(self.lang_class.field_host, None) + self.assertNotEquals(self.lang_class.field_port, None) + self.assertNotEquals(self.lang_class.field_ssl, None) + self.assertNotEquals(self.lang_class.field_tls, None) + self.assertNotEquals(self.lang_class.field_store_password, None) + self.assertNotEquals(self.lang_class.field_live_email_only, None) + self.assertNotEquals(self.lang_class.field_interval, None) + self.assertNotEquals(self.lang_class.field_mailbox, None) + + self.assertNotEquals(self.lang_class.field_action_1, None) + self.assertNotEquals(self.lang_class.field_chat_action_1, None) + self.assertNotEquals(self.lang_class.field_online_action_1, None) + self.assertNotEquals(self.lang_class.field_away_action_1, None) + self.assertNotEquals(self.lang_class.field_xa_action_1, None) + self.assertNotEquals(self.lang_class.field_dnd_action_1, None) + self.assertNotEquals(self.lang_class.field_offline_action_1, None) + + self.assertNotEquals(self.lang_class.field_action_2, None) + self.assertNotEquals(self.lang_class.field_chat_action_2, None) + self.assertNotEquals(self.lang_class.field_online_action_2, None) + self.assertNotEquals(self.lang_class.field_away_action_2, None) + self.assertNotEquals(self.lang_class.field_xa_action_2, None) + self.assertNotEquals(self.lang_class.field_dnd_action_2, None) + self.assertNotEquals(self.lang_class.field_offline_action_2, None) + + self.assertNotEquals(self.lang_class.field_default_from, None) + self.assertNotEquals(self.lang_class.field_default_account, None) + + self.assertNotEquals(self.lang_class.new_mail_subject, None) + self.assertNotEquals(self.lang_class.new_digest_subject, None) + + self.assertNotEquals(self.lang_class.type_imap_name, None) + self.assertNotEquals(self.lang_class.type_pop3_name, None) + self.assertNotEquals(self.lang_class.type_smtp_name, None) + + self.assertNotEquals(self.lang_class.send_mail_error_no_to_header_subject, + None) + self.assertNotEquals(self.lang_class.send_mail_error_no_to_header_body, + None) + self.assertNotEquals(self.lang_class.send_mail_ok_subject, None) + self.assertNotEquals(self.lang_class.send_mail_ok_body, None) + self.assertNotEquals(self.lang_class.help_message_body, None) + self.assertNotEquals(self.lang_class.command_force_check, None) + self.assertNotEquals(self.lang_class.command_force_check_1_description, None) + self.assertNotEquals(self.lang_class.command_get_email, None) + self.assertNotEquals(self.lang_class.command_get_email_1_description, None) + self.assertNotEquals(self.lang_class.command_get_email_2_description, None) + self.assertNotEquals(self.lang_class.field_email_subject, None) + self.assertNotEquals(self.lang_class.mail_subject, None) + self.assertNotEquals(self.lang_class.field_select_more_emails, None) + +class SubLanguage_TestCase(Language_TestCase): + """ + Test translation fallback mecanism : + jmc.lang.Lang.{translation class} -> jmc.lang.Lang.en -> jcl.lang.Lang.{translation class} -> jcl.lang.Lang.en + """ + + def test_fallback_jmc_en(self): + """ + if a translation does not exist in JMC. It falls back to the English + translation. + """ + value = self.lang_class.register_title + del self.lang_class.register_title + self.assertEquals(self.lang_class.register_title, + jmc.lang.Lang.en.register_title) + self.lang_class.register_title = value + + def test_fallback_jcl_current(self): + """ + if an attribut does not exist in JMC translation class nor in JMC + English class, it falls back to the current language in JCL. + """ + lang_class_value = self.lang_class.register_title + jmc_lang_en_value = jmc.lang.Lang.en.register_title + del self.lang_class.register_title + del jmc.lang.Lang.en.register_title + self.assertEquals(\ + self.lang_class.register_title, + jcl.lang.Lang.__dict__[self.lang_class.__name__].register_title) + jmc.lang.Lang.en.register_title = jmc_lang_en_value + self.lang_class.register_title = lang_class_value + + def test_fallback_jcl_en(self): + """ + if an attribut does not exist in JMC and is not translated in JCL, + it falls back to English in JCL + """ + lang_class_value = self.lang_class.register_title + jmc_lang_en_value = jmc.lang.Lang.en.register_title + jcl_lang_class_value = jcl.lang.Lang.__dict__[self.lang_class.__name__].register_title + del self.lang_class.register_title + del jmc.lang.Lang.en.register_title + del jcl.lang.Lang.__dict__[self.lang_class.__name__].register_title + self.assertEquals(\ + self.lang_class.register_title, + jcl.lang.Lang.en.register_title) + jcl.lang.Lang.__dict__[self.lang_class.__name__].register_title = jcl_lang_class_value + jmc.lang.Lang.en.register_title = jmc_lang_en_value + self.lang_class.register_title = lang_class_value + +class Language_fr_TestCase(SubLanguage_TestCase): + def setUp(self): + self.lang_class = Lang.fr + +class Language_nl_TestCase(Language_TestCase): + def setUp(self): + self.lang_class = Lang.nl + +class Language_es_TestCase(Language_TestCase): + def setUp(self): + self.lang_class = Lang.es + +class Language_pl_TestCase(Language_TestCase): + def setUp(self): + self.lang_class = Lang.pl + +class Language_cs_TestCase(Language_TestCase): + def setUp(self): + self.lang_class = Lang.cs + +class Language_ru_TestCase(Language_TestCase): + def setUp(self): + self.lang_class = Lang.ru + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(Lang_TestCase, 'test')) + suite.addTest(unittest.makeSuite(Language_TestCase, 'test')) + suite.addTest(unittest.makeSuite(Language_fr_TestCase, 'test')) + suite.addTest(unittest.makeSuite(Language_nl_TestCase, 'test')) + suite.addTest(unittest.makeSuite(Language_es_TestCase, 'test')) + suite.addTest(unittest.makeSuite(Language_pl_TestCase, 'test')) + suite.addTest(unittest.makeSuite(Language_cs_TestCase, 'test')) + suite.addTest(unittest.makeSuite(Language_ru_TestCase, 'test')) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/tests/jmc.conf @@ -0,0 +1,32 @@ +[jabber] +server: test_localhost +port: 42 +secret: test_secret +service_jid: test_jmc.localhost +#supported language: en, fr (See src/jmc/lang.py to add more) +language: test_en + +[db] +#type: mysql +type: test_sqlite +#host: root@localhost +host: root@localhost +name: /var/spool/jabber/test_jmc.db +#url: %(type)%(host)%(name)?debug=1&debugThreading=1 +db_url: %(type)s://%(host)s%(name)s + +[component] +pid_file: /var/run/jabber/test_jmc.pid +log_file: /tmp/jmc.log + +[jmc] +mail_default_encoding: test_iso-8859-1 + +[smtp] +smtp_default_login: testlogin +smtp_default_password: testpassword +smtp_default_host: testhost +smtp_default_port: 2525 +smtp_default_tls: True +smtp_default_label: SMTP Server +enable_smtp_default_account: True --- /dev/null +++ jmc-0.3b3/src/jmc/model/tests/email_generator.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +## email_generator.py +## Login : David Rousselie +## Started on Tue May 17 15:33:35 2005 +## $Id: email_generator.py,v 1.1 2005/07/11 20:39:31 dax Exp $ +## +## Copyright (C) 2005 +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +from email.Header import Header +from email.MIMEText import MIMEText +from email.MIMEMultipart import MIMEMultipart + +def _create_multipart(encoded): + msg = MIMEMultipart() + if encoded: + part1 = MIMEText("utf-8 multipart1 with no charset (éàê)", _charset = "") + msg.attach(part1) + part2 = MIMEText("Encoded multipart2 with 'iso-8859-15' charset (éàê)", \ + _charset = "iso-8859-15") + msg.attach(part2) + part3 = MIMEText("Encoded multipart3 with no charset (éàê)", \ + _charset = "") + msg.attach(part3) + else: + part1 = MIMEText("Not encoded multipart1") + msg.attach(part1) + part2 = MIMEText("Not encoded multipart2") + msg.attach(part2) + return msg + +def _create_singlepart(encoded): + if encoded: + return MIMEText("Encoded single part with 'iso-8859-15' charset (éàê)", \ + _charset = "iso-8859-15") + else: + return MIMEText("Not encoded single part") + +def generate(encoded, multipart, header): + msg = None + if multipart: + msg = _create_multipart(encoded) + else: + msg = _create_singlepart(encoded) + if header: + if encoded: + msg['Subject'] = Header("encoded subject (éàê)", "iso-8859-15") + msg['From'] = Header("encoded from (éàê)", "iso-8859-15") + else: + msg['Subject'] = Header("not encoded subject") + msg['From'] = Header("not encoded from") + return msg + --- /dev/null +++ jmc-0.3b3/src/jmc/model/tests/account.py @@ -0,0 +1,1140 @@ +# -*- coding: utf-8 -*- +## +## test_account.py +## Login : +## Started on Wed Feb 14 08:23:17 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2007 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import unittest +import thread + +from jcl.tests import JCLTestCase +import jcl.model as model +from jcl.error import FieldError +from jcl.model.account import Account, PresenceAccount, User +import jmc.model.account +from jmc.model.account import MailAccount, POP3Account, IMAPAccount, \ + GlobalSMTPAccount, AbstractSMTPAccount, SMTPAccount +from jmc.lang import Lang + +from jcl.model.tests.account import Account_TestCase, \ + PresenceAccount_TestCase, InheritableAccount_TestCase, \ + ExampleAccount +from jmc.model.tests import email_generator, server + +class AccountModule_TestCase(unittest.TestCase): + def test_validate_login_with_empty_login(self): + self.assertRaises(FieldError, jmc.model.account.validate_login, + None, None, None) + + def test_validate_login_with_login_with_whitespace(self): + self.assertRaises(FieldError, jmc.model.account.validate_login, + "login with spaces", None, None) + + def test_validate_host_with_empty_login(self): + self.assertRaises(FieldError, jmc.model.account.validate_host, + None, None, None) + + def test_validate_host_with_host_with_whitespace(self): + self.assertRaises(FieldError, jmc.model.account.validate_host, + "host with spaces", None, None) + +class MailAccount_TestCase(PresenceAccount_TestCase): + def setUp(self): + PresenceAccount_TestCase.setUp(self, tables=[MailAccount]) + self.account = MailAccount(user=User(jid="user1@test.com"), + name="account1", + jid="account1@jmc.test.com") + self.account_class = MailAccount + + def make_test(email_type, tested_func, expected_res): + def inner(self): + encoded, multipart, header = email_type + email = email_generator.generate(encoded, + multipart, + header) + part = tested_func(self, email) + self.assertEquals(part, expected_res) + return inner + + test_get_decoded_part_not_encoded = \ + make_test((False, False, False), \ + lambda self, email: \ + self.account.get_decoded_part(email, None), + u"Not encoded single part") + + test_get_decoded_part_encoded = \ + make_test((True, False, False), + lambda self, email: \ + self.account.get_decoded_part(email, None), + u"Encoded single part with 'iso-8859-15' charset (éàê)") + + test_format_message_summary_not_encoded = \ + make_test((False, False, True), + lambda self, email: \ + self.account.format_message_summary(email), + (u"From : not encoded from\nSubject : not encoded subject\n\n", + u"not encoded from")) + + test_format_message_summary_encoded = \ + make_test((True, False, True), + lambda self, email: \ + self.account.format_message_summary(email), + (u"From : encoded from (éàê)\nSubject : encoded subject " + \ + u"(éàê)\n\n", + u"encoded from (éàê)")) + + test_format_message_summary_partial_encoded = \ + make_test((True, False, True), + lambda self, email: \ + email.replace_header("Subject", + "\" " + str(email["Subject"]) \ + + " \" not encoded part") or \ + email.replace_header("From", + "\" " + str(email["From"]) \ + + " \" not encoded part") or \ + self.account.format_message_summary(email), + (u"From : \"encoded from (éàê)\" not encoded part\nSubject " + \ + u": \"encoded subject (éàê)\" not encoded part\n\n", + u"\"encoded from (éàê)\" not encoded part")) + + test_format_message_single_not_encoded = \ + make_test((False, False, True), + lambda self, email: \ + self.account.format_message(email), + (u"From : not encoded from\nSubject : not encoded subject" + \ + u"\n\nNot encoded single part\n", + u"not encoded from")) + + test_format_message_single_encoded = \ + make_test((True, False, True), + lambda self, email: \ + self.account.format_message(email), + (u"From : encoded from (éàê)\nSubject : encoded subject " + \ + u"(éàê)\n\nEncoded single part with 'iso-8859-15' charset" + \ + u" (éàê)\n", + u"encoded from (éàê)")) + + test_format_message_multi_not_encoded = \ + make_test((False, True, True), + lambda self, email: \ + self.account.format_message(email), + (u"From : not encoded from\nSubject : not encoded subject" + \ + u"\n\nNot encoded multipart1\nNot encoded multipart2\n", + u"not encoded from")) + + test_format_message_multi_encoded = \ + make_test((True, True, True), + lambda self, email: \ + self.account.format_message(email), + (u"From : encoded from (éàê)\nSubject : encoded subject (éà" + \ + u"ê)\n\nutf-8 multipart1 with no charset (éàê)" + \ + u"\nEncoded multipart2 with 'iso-8859-15' charset (éàê)\n" + \ + u"Encoded multipart3 with no charset (éàê)\n", + u"encoded from (éàê)")) + + def test_get_default_status_msg(self): + """ + Get default status message for MailAccount. + Should raise NotImplementedError because get_type() method + is not implemented + """ + try: + self.account.get_default_status_msg(Lang.en) + except NotImplementedError: + return + fail("No NotImplementedError raised") + +class POP3Account_TestCase(InheritableAccount_TestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[Account, PresenceAccount, User, + MailAccount, POP3Account]) + self.pop3_account = POP3Account(user=User(jid="user1@test.com"), + name="account1", + jid="account1@jmc.test.com", + login="login") + self.pop3_account.password = "pass" + self.pop3_account.host = "localhost" + self.pop3_account.port = 1110 + self.pop3_account.ssl = False + model.db_disconnect() + self.account_class = POP3Account + + def make_test(responses=None, queries=None, core=None): + def inner(self): + self.server = server.DummyServer("localhost", 1110) + thread.start_new_thread(self.server.serve, ()) + self.server.responses = ["+OK connected\r\n", + "+OK name is a valid mailbox\r\n", + "+OK pass\r\n"] + if responses: + self.server.responses += responses + self.server.queries = ["USER login\r\n", + "PASS pass\r\n"] + if queries: + self.server.queries += queries + self.server.queries += ["QUIT\r\n"] + self.pop3_account.connect() + self.failUnless(self.pop3_account.connection, + "Cannot establish connection") + if core: + model.db_connect() + core(self) + model.db_disconnect() + self.pop3_account.disconnect() + self.failUnless(self.server.verify_queries(), + "Sended queries does not match expected queries.") + return inner + + test_connection = make_test + + test_get_mail_list_summary = \ + make_test(["+OK 2 20\r\n", + "+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: mail subject 1\r\n.\r\n", + "+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: mail subject 2\r\n.\r\n", + "+OK\r\n"], + ["STAT\r\n", + "TOP 1 0\r\n", + "TOP 2 0\r\n", + "RSET\r\n"], + lambda self: \ + self.assertEquals(self.pop3_account.get_mail_list_summary(), + [("1", "mail subject 1"), + ("2", "mail subject 2")])) + + test_get_mail_list_summary_start_index = \ + make_test(["+OK 3 30\r\n", + "+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: mail subject 2\r\n.\r\n", + "+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: mail subject 3\r\n.\r\n", + "+OK\r\n"], + ["STAT\r\n", + "TOP 2 0\r\n", + "TOP 3 0\r\n", + "RSET\r\n"], + lambda self: \ + self.assertEquals(self.pop3_account.get_mail_list_summary(start_index=2), + [("2", "mail subject 2"), + ("3", "mail subject 3")])) + + test_get_mail_list_summary_end_index = \ + make_test(["+OK 3 30\r\n", + "+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: mail subject 1\r\n.\r\n", + "+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: mail subject 2\r\n.\r\n", + "+OK\r\n"], + ["STAT\r\n", + "TOP 1 0\r\n", + "TOP 2 0\r\n", + "RSET\r\n"], + lambda self: \ + self.assertEquals(self.pop3_account.get_mail_list_summary(end_index=2), + [("1", "mail subject 1"), + ("2", "mail subject 2")])) + + test_get_new_mail_list = \ + make_test(["+OK 2 20\r\n"], + ["STAT\r\n"], + lambda self: \ + self.assertEquals(self.pop3_account.get_new_mail_list(), + ["1", "2"])) + + test_get_mail_summary = \ + make_test(["+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: subject test\r\n\r\n" + \ + "mymessage\r\n.\r\n", + "+OK\r\n"], + ["RETR 1\r\n", + "RSET\r\n"], + lambda self: \ + self.assertEquals(self.pop3_account.get_mail_summary(1), + (u"From : user@test.com\n" + \ + u"Subject : subject test\n\n", + u"user@test.com"))) + + test_get_mail = \ + make_test(["+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: subject test\r\n\r\n" + \ + "mymessage\r\n.\r\n", + "+OK\r\n"], + ["RETR 1\r\n", + "RSET\r\n"], + lambda self: \ + self.assertEquals(self.pop3_account.get_mail(1), + (u"From : user@test.com\n" + \ + u"Subject : subject test\n\n" + \ + u"mymessage\n", + u"user@test.com"))) + + test_unsupported_reset_command_get_mail_summary = \ + make_test(["+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: subject test\r\n\r\n" + \ + "mymessage\r\n.\r\n", + "-ERR unknown command\r\n"], + ["RETR 1\r\n", + "RSET\r\n"], + lambda self: \ + self.assertEquals(self.pop3_account.get_mail_summary(1), + (u"From : user@test.com\n" + \ + u"Subject : subject test\n\n", + u"user@test.com"))) + + test_unsupported_reset_command_get_mail = \ + make_test(["+OK 10 octets\r\n" + \ + "From: user@test.com\r\n" + \ + "Subject: subject test\r\n\r\n" + \ + "mymessage\r\n.\r\n", + "-ERR unknown command\r\n"], + ["RETR 1\r\n", + "RSET\r\n"], + lambda self: \ + self.assertEquals(self.pop3_account.get_mail(1), + (u"From : user@test.com\n" + \ + u"Subject : subject test\n\n" + \ + u"mymessage\n", + u"user@test.com"))) + + def test_get_next_mail_index_empty(self): + """ + Test get_next_mail_index with empty mail_list parameter. + """ + mail_list = [] + self.pop3_account.nb_mail = 0 + self.pop3_account.lastmail = 0 + result = [] + for elt in self.pop3_account.get_next_mail_index(mail_list): + result.append(elt) + self.assertEquals(result, []) + + def test_get_next_mail_index(self): + """ + Test get_next_mail_index first check. + """ + mail_list = [1, 2, 3, 4] + self.pop3_account.nb_mail = 4 + self.pop3_account.lastmail = 0 + result = [] + for elt in self.pop3_account.get_next_mail_index(mail_list): + result.append(elt) + self.assertEquals(result, [1, 2, 3, 4]) + self.assertEquals(self.pop3_account.lastmail, 4) + + def test_get_next_mail_index_second_check(self): + """ + Test get_next_mail_index second check (no parallel checking). + """ + mail_list = [1, 2, 3, 4, 5, 6, 7, 8] + self.pop3_account.nb_mail = 8 + self.pop3_account.lastmail = 4 + result = [] + for elt in self.pop3_account.get_next_mail_index(mail_list): + result.append(elt) + self.assertEquals(result, [5, 6, 7, 8]) + self.assertEquals(self.pop3_account.lastmail, 8) + + def test_get_next_mail_index_second_check_parallel_check(self): + """ + Test get_next_mail_index second check (with parallel checking + but not more new emails than last index jmc stopped: + 3 new emails after another client checked emails). + """ + mail_list = [1, 2, 3] + self.pop3_account.nb_mail = 3 + self.pop3_account.lastmail = 4 + result = [] + for elt in self.pop3_account.get_next_mail_index(mail_list): + result.append(elt) + self.assertEquals(result, [1, 2, 3]) + self.assertEquals(self.pop3_account.lastmail, 3) + + def test_get_next_mail_index_second_check_bug_parallel_check(self): + """ + Test get_next_mail_index second check (with parallel checking + but with more new emails than last index jmc stopped: + 5 new emails after another client checked emails). Cannot make + the difference with one new email since last jmc email check!! + """ + mail_list = [1, 2, 3, 4, 5] + self.pop3_account.nb_mail = 5 + self.pop3_account.lastmail = 4 + result = [] + for elt in self.pop3_account.get_next_mail_index(mail_list): + result.append(elt) + # with no bug it should be: + # self.assertEquals(result, [1, 2, 3, 4, 5]) + self.assertEquals(result, [5]) + self.assertEquals(self.pop3_account.lastmail, 5) + + def test_get_default_status_msg(self): + """ + Get default status message for POP3Account. + """ + status_msg = self.pop3_account.get_default_status_msg(Lang.en) + self.assertEquals(status_msg, "pop3://login@localhost:1110") + + def test_get_default_status_msg_ssl(self): + """ + Get default status message for SSL POP3Account. + """ + self.pop3_account.ssl = True + status_msg = self.pop3_account.get_default_status_msg(Lang.en) + self.assertEquals(status_msg, "pop3s://login@localhost:1110") + +class IMAPAccount_TestCase(InheritableAccount_TestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[Account, PresenceAccount, User, + MailAccount, IMAPAccount]) + self.imap_account = IMAPAccount(user=User(jid="user1@test.com"), + name="account1", + jid="account1@jmc.test.com", + login="login") + self.imap_account.password = "pass" + self.imap_account.host = "localhost" + self.imap_account.port = 1143 + self.imap_account.ssl = False + self.account_class = IMAPAccount + + def make_test(self, responses=None, queries=None, core=None): + def inner(): + self.server = server.DummyServer("localhost", 1143) + thread.start_new_thread(self.server.serve, ()) + self.server.responses = ["* OK [CAPABILITY IMAP4 LOGIN-REFERRALS " + \ + "AUTH=PLAIN]\r\n", \ + lambda data: "* CAPABILITY IMAP4 " + \ + "LOGIN-REFERRALS AUTH=PLAIN\r\n" + \ + data.split()[0] + \ + " OK CAPABILITY completed\r\n", \ + lambda data: data.split()[0] + \ + " OK LOGIN completed\r\n"] + if responses: + self.server.responses += responses + self.server.queries = ["^[^ ]* CAPABILITY", \ + "^[^ ]* LOGIN login \"pass\""] + if queries: + self.server.queries += queries + self.server.queries += ["^[^ ]* LOGOUT"] + if not self.imap_account.connected: + self.imap_account.connect() + self.failUnless(self.imap_account.connection, \ + "Cannot establish connection") + if core: + model.db_connect() + core(self) + model.db_disconnect() + if self.imap_account.connected: + self.imap_account.disconnect() + self.failUnless(self.server.verify_queries()) + return inner + + def test_connection(self): + test_func = self.make_test() + test_func() + + def test_get_mail_list_summary(self): + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* 1 FETCH ((RFC822.header) {38}\r\n" + \ + "Subject: mail subject 1\r\n\r\nbody text\r\n)\r\n" + \ + "* 2 FETCH ((RFC822.header) {38}\r\n" + \ + "Subject: mail subject 2\r\n\r\nbody text\r\n)\r\n" + \ + data.split()[0] + " OK FETCH completed\r\n"], + ["^[^ ]* EXAMINE INBOX", + "^[^ ]* FETCH 1:20 RFC822.header"], + lambda self: \ + self.assertEquals(self.imap_account.get_mail_list_summary(), + [('1', 'mail subject 1'), + ('2', 'mail subject 2')])) + test_func() + + def test_get_mail_list_summary_inbox_does_not_exist(self): + self.__test_select_inbox_does_not_exist(\ + lambda: self.imap_account.get_mail_list_summary(), readonly=True) + + def test_get_mail_list_summary_start_index(self): + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* 2 FETCH ((RFC822.header) {38}\r\n" + \ + "Subject: mail subject 2\r\n\r\nbody text\r\n)\r\n" + \ + "* 3 FETCH ((RFC822.header) {38}\r\n" + \ + "Subject: mail subject 3\r\n\r\nbody text\r\n)\r\n" + \ + data.split()[0] + " OK FETCH completed\r\n"], + ["^[^ ]* EXAMINE INBOX", + "^[^ ]* FETCH 2:20 RFC822.header"], + lambda self: \ + self.assertEquals(self.imap_account.get_mail_list_summary(start_index=2), + [('2', 'mail subject 2'), + ('3', 'mail subject 3')])) + test_func() + + def test_get_mail_list_summary_end_index(self): + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* 1 FETCH ((RFC822.header) {38}\r\n" + \ + "Subject: mail subject 1\r\n\r\nbody text\r\n)\r\n" + \ + "* 2 FETCH ((RFC822.header) {38}\r\n" + \ + "Subject: mail subject 2\r\n\r\nbody text\r\n)\r\n" + \ + data.split()[0] + " OK FETCH completed\r\n"], + ["^[^ ]* EXAMINE INBOX", + "^[^ ]* FETCH 1:2 RFC822.header"], + lambda self: \ + self.assertEquals(self.imap_account.get_mail_list_summary(end_index=2), + [('1', 'mail subject 1'), + ('2', 'mail subject 2')])) + test_func() + + def test_get_new_mail_list(self): + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* SEARCH 9 10\r\n" + \ + data.split()[0] + " OK SEARCH completed\r\n"], + ["^[^ ]* SELECT INBOX", + "^[^ ]* SEARCH RECENT"], + lambda self: \ + self.assertEquals(self.imap_account.get_new_mail_list(), + ['9', '10'])) + test_func() + + def __test_select_inbox_does_not_exist(self, tested_func, + exception_message="Mailbox does not exist", + readonly=False): + def check_func(self): + try: + tested_func() + except Exception, e: + self.assertEquals(str(e), exception_message) + return + self.fail("No exception raised when selecting non existing mailbox") + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " NO Mailbox does not exist\r\n"], + ["^[^ ]* " + (readonly and "EXAMINE" or "SELECT") + " INBOX"], + check_func) + test_func() + + def test_get_new_mail_list_inbox_does_not_exist(self): + self.__test_select_inbox_does_not_exist(\ + lambda: self.imap_account_get_new_mail_list()) + + def test_get_new_mail_list_delimiter1(self): + self.imap_account.mailbox = "INBOX/dir1/subdir2" + self.imap_account.delimiter = "." + test_func = self.make_test( \ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* SEARCH 9 10\r\n" + \ + data.split()[0] + " OK SEARCH completed\r\n"], + ["^[^ ]* SELECT \"?INBOX\.dir1\.subdir2\"?", + "^[^ ]* SEARCH RECENT"], + lambda self: \ + self.assertEquals(self.imap_account.get_new_mail_list(), + ['9', '10'])) + test_func() + + def test_get_new_mail_list_delimiter2(self): + self.imap_account.mailbox = "INBOX/dir1/subdir2" + self.imap_account.delimiter = "/" + test_func = self.make_test( \ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* SEARCH 9 10\r\n" + \ + data.split()[0] + " OK SEARCH completed\r\n"], + ["^[^ ]* SELECT \"?INBOX/dir1/subdir2\"?", + "^[^ ]* SEARCH RECENT"], + lambda self: \ + self.assertEquals(self.imap_account.get_new_mail_list(), + ['9', '10'])) + test_func() + + def test_get_mail_summary(self): + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* 1 FETCH ((RFC822) {12}\r\nbody" + \ + " text\r\n)\r\n" + \ + data.split()[0] + " OK FETCH completed\r\n"], + ["^[^ ]* EXAMINE INBOX", + "^[^ ]* FETCH 1 \(RFC822.header\)"], + lambda self: \ + self.assertEquals(self.imap_account.get_mail_summary(1), + (u"From : None\nSubject : None\n\n", + u"None"))) + test_func() + + def test_get_mail_summary_inbox_does_not_exist(self): + self.__test_select_inbox_does_not_exist(\ + lambda: self.imap_account.get_mail_summary(1), + "Mailbox does not exist (email 1)", True) + + def test_get_new_mail_list_inbox_does_not_exist(self): + def check_func(self): + try: + self.imap_account.get_new_mail_list() + except Exception, e: + self.assertEquals(str(e), "Mailbox does not exist") + return + self.fail("No exception raised when selecting non existing mailbox") + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " NO Mailbox does not exist\r\n"], + ["^[^ ]* SELECT INBOX"], + check_func) + test_func() + + def test_get_mail_summary_delimiter(self): + self.imap_account.mailbox = "INBOX/dir1/subdir2" + self.imap_account.delimiter = "." + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" +\ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" +\ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* 1 FETCH ((RFC822) {12}\r\nbody" + \ + " text\r\n)\r\n" + \ + data.split()[0] + " OK FETCH completed\r\n"], + ["^[^ ]* EXAMINE \"?INBOX\.dir1\.subdir2\"?", + "^[^ ]* FETCH 1 \(RFC822.header\)"], + lambda self: \ + self.assertEquals(self.imap_account.get_mail_summary(1), + (u"From : None\nSubject : None\n\n", + u"None"))) + test_func() + + def test_get_mail(self): + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* 1 FETCH ((RFC822) {11}\r\nbody" + \ + " text\r\n)\r\n" + \ + data.split()[0] + " OK FETCH completed\r\n"], + ["^[^ ]* EXAMINE INBOX", + "^[^ ]* FETCH 1 \(RFC822\)"], + lambda self: \ + self.assertEquals(self.imap_account.get_mail(1), + (u"From : None\nSubject : None\n\nbody text\r\n\n", + u"None"))) + test_func() + + def test_get_mail_inbox_does_not_exist(self): + self.__test_select_inbox_does_not_exist(\ + lambda: self.imap_account.get_mail(1), + "Mailbox does not exist (email 1)", True) + + def test_get_mail_delimiter(self): + self.imap_account.mailbox = "INBOX/dir1/subdir2" + self.imap_account.delimiter = "." + test_func = self.make_test(\ + [lambda data: "* 42 EXISTS\r\n* 1 RECENT\r\n* OK" + \ + " [UNSEEN 9]\r\n* FLAGS (\Deleted \Seen\*)\r\n*" + \ + " OK [PERMANENTFLAGS (\Deleted \Seen\*)\r\n" + \ + data.split()[0] + \ + " OK [READ-WRITE] SELECT completed\r\n", + lambda data: "* 1 FETCH ((RFC822) {11}\r\nbody" + \ + " text\r\n)\r\n" + \ + data.split()[0] + " OK FETCH completed\r\n"], + ["^[^ ]* EXAMINE \"?INBOX\.dir1\.subdir2\"?", + "^[^ ]* FETCH 1 \(RFC822\)"], + lambda self: \ + self.assertEquals(self.imap_account.get_mail(1), + (u"From : None\nSubject : None\n\nbody text\r\n\n", + u"None"))) + test_func() + + def test_build_folder_cache(self): + test_func = self.make_test(\ + [lambda data: '* LIST () "." "INBOX"\r\n' + \ + '* LIST () "." "INBOX.dir1"\r\n' + \ + '* LIST () "." "INBOX.dir1.subdir1"\r\n' + \ + '* LIST () "." "INBOX.dir1.subdir2"\r\n' + \ + '* LIST () "." "INBOX.dir2"\r\n' + \ + data.split()[0] + ' OK LIST completed\r\n'], + ["^[^ ]* LIST \"\" \*"], + lambda self: self.assertEquals(self.imap_account._build_folder_cache(), + {"INBOX": + {"dir1": + {"subdir1": {}, + "subdir2": {}}, + "dir2": {}}})) + test_func() + + def test_ls_dir_base(self): + self.test_build_folder_cache() + self.assertEquals(self.imap_account.ls_dir(""), + ["INBOX"]) + + def test_ls_dir_subdir(self): + self.test_build_folder_cache() + result = self.imap_account.ls_dir("INBOX") + result.sort() + self.assertEquals(result, + ["dir1", "dir2"]) + + def test_ls_dir_subsubdir_delim1(self): + self.test_build_folder_cache() + self.imap_account.default_delimiter = "." + result = self.imap_account.ls_dir("INBOX/dir1") + result.sort() + self.assertEquals(result, + ["subdir1", "subdir2"]) + + def test_ls_dir_subsubdir_delim2(self): + self.test_build_folder_cache() + result = self.imap_account.ls_dir("INBOX/dir1") + result.sort() + self.assertEquals(result, + ["subdir1", "subdir2"]) + + def test_populate_handler(self): + self.assertEquals(".", self.imap_account.delimiter) + self.imap_account.mailbox = "INBOX/dir1/subdir2" + def call_func(self): + self.imap_account.populate_handler() + self.assertEquals("INBOX.dir1.subdir2", self.imap_account.mailbox) + test_func = self.make_test(\ + [lambda data: '* LIST () "." "INBOX.dir1.subdir2"\r\n' + \ + data.split()[0] + ' OK LIST completed\r\n'], + ["^[^ ]* LIST \"?INBOX.dir1.subdir2\"? \*"], + call_func) + test_func() + + def test_populate_handler_wrong_default_delimiter(self): + self.imap_account.delimiter = "/" + self.imap_account.mailbox = "INBOX/dir1/subdir2" + def call_func(self): + self.imap_account.populate_handler() + self.assertEquals("INBOX.dir1.subdir2", self.imap_account.mailbox) + self.assertEquals(".", self.imap_account.delimiter) + test_func = self.make_test(\ + [lambda data: data.split()[0] + ' OK LIST completed\r\n', + lambda data: '* LIST () "." "INBOX.dir1.subdir2"\r\n' + \ + data.split()[0] + ' OK LIST completed\r\n'], + ["^[^ ]* LIST \"?INBOX/dir1/subdir2\"? \*", + "^[^ ]* LIST \"?INBOX.dir1.subdir2\"? \*"], + call_func) + test_func() + + def test_populate_handler_wrong_mailbox(self): + self.assertEquals(".", self.imap_account.delimiter) + self.imap_account.mailbox = "INBOX.dir1.subdir2" + def call_func(self): + try: + self.imap_account.populate_handler() + except Exception, e: + return + self.fail("Exception should have been raised") + test_func = self.make_test(\ + [lambda data: data.split()[0] + ' ERR LIST completed\r\n'], + ["^[^ ]* LIST \"?INBOX.dir1.subdir2\"? \*"], + call_func) + test_func() + + def check_get_next_mail_index(self, mail_list): + """ + Common tests for get_next_mail_index method. + """ + result = [] + original_mail_list = [elt for elt in mail_list] + for elt in self.imap_account.get_next_mail_index(mail_list): + result.append(elt) + self.assertEquals(mail_list, []) + self.assertEquals(result, original_mail_list) + + def test_get_next_mail_index_empty(self): + """ + Test get_next_mail_index with empty mail_list parameter. + """ + mail_list = [] + self.check_get_next_mail_index(mail_list) + + def test_get_next_mail_index(self): + """ + Test get_next_mail_index. + """ + mail_list = [1, 2, 3, 4] + self.check_get_next_mail_index(mail_list) + + def test_get_default_status_msg(self): + """ + Get default status message for IMAPAccount. + """ + status_msg = self.imap_account.get_default_status_msg(Lang.en) + self.assertEquals(status_msg, "imap://login@localhost:1143") + + def test_get_default_status_msg_ssl(self): + """ + Get default status message for SSL IMAPAccount. + """ + self.imap_account.ssl = True + status_msg = self.imap_account.get_default_status_msg(Lang.en) + self.assertEquals(status_msg, "imaps://login@localhost:1143") + +class AbstractSMTPAccount_TestCase(Account_TestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[Account, ExampleAccount, User, + GlobalSMTPAccount, AbstractSMTPAccount]) + self.account_class = AbstractSMTPAccount + + def test_default_account_post_func_no_default_true(self): + user1 = User(jid="user1@test.com") + account11 = AbstractSMTPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account12 = AbstractSMTPAccount(user=user1, + name="account12", + jid="account12@jmc.test.com") + (name, field_type, field_options, post_func, default_func) = \ + AbstractSMTPAccount.get_register_fields()[0] + value = post_func("True", None, "user1@test.com") + self.assertTrue(value) + + def test_default_account_post_func_no_default_false(self): + user1 = User(jid="user1@test.com") + account11 = AbstractSMTPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account12 = AbstractSMTPAccount(user=user1, + name="account12", + jid="account12@jmc.test.com") + (name, field_type, field_options, post_func, default_func) = \ + AbstractSMTPAccount.get_register_fields()[0] + value = post_func("False", None, "user1@test.com") + self.assertTrue(value) + + def test_default_account_post_func_true(self): + user1 = User(jid="user1@test.com") + account11 = AbstractSMTPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account12 = AbstractSMTPAccount(user=user1, + name="account12", + jid="account12@jmc.test.com") + account12.default_account = True + (name, field_type, field_options, post_func, default_func) = \ + AbstractSMTPAccount.get_register_fields()[0] + value = post_func("True", None, "user1@test.com") + self.assertTrue(value) + self.assertFalse(account12.default_account) + + def test_default_account_post_func_false(self): + user1 = User(jid="user1@test.com") + account11 = AbstractSMTPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account12 = AbstractSMTPAccount(user=user1, + name="account12", + jid="account12@jmc.test.com") + account12.default_account = True + (name, field_type, field_options, post_func, default_func) = \ + AbstractSMTPAccount.get_register_fields()[0] + value = post_func("False", None, "user1@test.com") + self.assertFalse(value) + self.assertTrue(account12.default_account) + + def test_create_email(self): + account11 = AbstractSMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + email = account11.create_email("from@test.com", + "to@test.com", + "subject", + "body") + self.assertEqual(email['From'], "from@test.com") + self.assertEqual(email['To'], "to@test.com") + self.assertEqual(email['Subject'], "subject") + self.assertEqual(email.get_payload(), "body") + + def test_create_email_other_headers(self): + account11 = AbstractSMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + email = account11.create_email("from@test.com", + "to@test.com", + "subject", + "body", + {"Bcc": "bcc@test.com", + "Cc": "cc@test.com"}) + self.assertEqual(email['From'], "from@test.com") + self.assertEqual(email['To'], "to@test.com") + self.assertEqual(email['Subject'], "subject") + self.assertEqual(email['Bcc'], "bcc@test.com") + self.assertEqual(email['Cc'], "cc@test.com") + self.assertEqual(email.get_payload(), "body") + +class SMTPAccount_TestCase(Account_TestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[Account, ExampleAccount, User, + GlobalSMTPAccount, + AbstractSMTPAccount, SMTPAccount]) + self.account_class = SMTPAccount + + def make_test(self, responses=None, queries=None, core=None): + def inner(): + self.server = server.DummyServer("localhost", 1025) + thread.start_new_thread(self.server.serve, ()) + self.server.responses = [] + if responses: + self.server.responses += responses + self.server.responses += ["221 localhost closing connection\r\n"] + self.server.queries = [] + if queries: + self.server.queries += queries + self.server.queries += ["quit\r\n"] + if core: + model.db_connect() + core(self) + model.db_disconnect() + self.failUnless(self.server.verify_queries()) + return inner + + def test_send_email_esmtp_no_auth(self): + model.db_connect() + smtp_account = SMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + smtp_account.host = "localhost" + smtp_account.port = 1025 + model.db_disconnect() + email = smtp_account.create_email("from@test.com", + "to@test.com", + "subject", + "body") + test_func = self.make_test(["220 localhost ESMTP\r\n", + "250-localhost Hello 127.0.0.1\r\n" + + "250-SIZE 52428800\r\n" + + "250-PIPELINING\r\n" + + "250 HELP\r\n", + "250 OK\r\n", + "250 Accepted\r\n", + "354 Enter message\r\n", + None, None, None, None, + None, None, None, None, + "250 OK\r\n"], + ["ehlo .*\r\n", + "mail FROM:<" + str(email['From']) + ">.*", + "rcpt TO:<" + str(email['To']) + ">\r\n", + "data\r\n"] + + email.as_string().split("\n") + [".\r\n"], + lambda self: \ + smtp_account.send_email(email)) + test_func() + + def test_send_email_no_auth(self): + model.db_connect() + smtp_account = SMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + smtp_account.host = "localhost" + smtp_account.port = 1025 + model.db_disconnect() + email = smtp_account.create_email("from@test.com", + "to@test.com", + "subject", + "body") + test_func = self.make_test(["220 localhost SMTP\r\n", + "504 ESMTP not supported\r\n", + "250-localhost Hello 127.0.0.1\r\n" + + "250-SIZE 52428800\r\n" + + "250-PIPELINING\r\n" + + "250 HELP\r\n", + "250 OK\r\n", + "250 Accepted\r\n", + "354 Enter message\r\n", + None, None, None, None, + None, None, None, None, + "250 OK\r\n"], + ["ehlo .*\r\n", + "helo .*\r\n", + "mail FROM:<" + str(email['From']) + ">.*", + "rcpt TO:<" + str(email['To']) + ">\r\n", + "data\r\n"] + + email.as_string().split("\n") + [".\r\n"], + lambda self: \ + smtp_account.send_email(email)) + test_func() + + def test_send_email_esmtp_auth(self): + model.db_connect() + smtp_account = SMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + smtp_account.host = "localhost" + smtp_account.port = 1025 + smtp_account.login = "user" + smtp_account.password = "pass" + model.db_disconnect() + email = smtp_account.create_email("from@test.com", + "to@test.com", + "subject", + "body") + test_func = self.make_test(["220 localhost ESMTP\r\n", + "250-localhost Hello 127.0.0.1\r\n" + + "250-SIZE 52428800\r\n" + + "250-AUTH PLAIN LOGIN CRAM-MD5\r\n" + + "250-PIPELINING\r\n" + + "250 HELP\r\n", + "334 ZGF4IDNmNDM2NzY0YzBhNjgyMTQ1MzhhZGNiMjE2YTYxZjRm\r\n", + "235 Authentication succeeded\r\n", + "250 OK\r\n", + "250 Accepted\r\n", + "354 Enter message\r\n", + None, None, None, None, + None, None, None, None, + "250 OK\r\n"], + ["ehlo .*\r\n", + "AUTH CRAM-MD5\r\n", + ".*\r\n", + "mail FROM:<" + str(email['From']) + ">.*", + "rcpt TO:<" + str(email['To']) + ">\r\n", + "data\r\n"] + + email.as_string().split("\n") + [".\r\n"], + lambda self: \ + smtp_account.send_email(email)) + test_func() + + def test_send_email_esmtp_auth_method2(self): + model.db_connect() + smtp_account = SMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + smtp_account.host = "localhost" + smtp_account.port = 1025 + smtp_account.login = "user" + smtp_account.password = "pass" + model.db_disconnect() + email = smtp_account.create_email("from@test.com", + "to@test.com", + "subject", + "body") + test_func = self.make_test(["220 localhost ESMTP\r\n", + "250-localhost Hello 127.0.0.1\r\n" + + "250-SIZE 52428800\r\n" + + "250-AUTH PLAIN LOGIN CRAM-MD5\r\n" + + "250-PIPELINING\r\n" + + "250 HELP\r\n", + "334 ZGF4IDNmNDM2NzY0YzBhNjgyMTQ1MzhhZGNiMjE2YTYxZjRm\r\n", + "535 Incorrect Authentication data\r\n", + "334 asd235r4\r\n", + "235 Authentication succeeded\r\n", + "250 OK\r\n", + "250 Accepted\r\n", + "354 Enter message\r\n", + None, None, None, None, + None, None, None, None, + "250 OK\r\n"], + ["ehlo .*\r\n", + "AUTH CRAM-MD5\r\n", + ".*\r\n", + "AUTH LOGIN .*\r\n", + ".*\r\n", + "mail FROM:<" + str(email['From']) + ">.*", + "rcpt TO:<" + str(email['To']) + ">\r\n", + "data\r\n"] + + email.as_string().split("\n") + [".\r\n"], + lambda self: \ + smtp_account.send_email(email)) + test_func() + + def test_get_default_status_msg(self): + """ + Get default status message for IMAPAccount. + """ + smtp_account = SMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + smtp_account.host = "localhost" + smtp_account.port = 1025 + smtp_account.login = "user" + smtp_account.password = "pass" + status_msg = smtp_account.get_default_status_msg(Lang.en) + self.assertEquals(status_msg, "smtp://user@localhost:1025") + + def test_get_default_status_msg_ssl(self): + """ + Get default status message for SSL IMAPAccount. + """ + smtp_account = SMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + smtp_account.host = "localhost" + smtp_account.port = 1025 + smtp_account.login = "user" + smtp_account.password = "pass" + smtp_account.tls = True + status_msg = smtp_account.get_default_status_msg(Lang.en) + self.assertEquals(status_msg, "smtps://user@localhost:1025") + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(AccountModule_TestCase, 'test')) + suite.addTest(unittest.makeSuite(MailAccount_TestCase, 'test')) + suite.addTest(unittest.makeSuite(POP3Account_TestCase, 'test')) + suite.addTest(unittest.makeSuite(IMAPAccount_TestCase, 'test')) + suite.addTest(unittest.makeSuite(AbstractSMTPAccount_TestCase, 'test')) + suite.addTest(unittest.makeSuite(SMTPAccount_TestCase, 'test')) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/model/tests/__init__.py @@ -0,0 +1,14 @@ +"""JMC test module""" +__revision__ = "" + +import unittest + +from jmc.model.tests import account + +def suite(): + suite = unittest.TestSuite() + suite.addTest(account.suite()) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/model/tests/server.py @@ -0,0 +1,205 @@ +## +## dummy_server.py +## Login : David Rousselie +## Started on Fri May 13 12:53:17 2005 +## $Id: dummy_server.py,v 1.1 2005/07/11 20:39:31 dax Exp $ +## +## Copyright (C) 2005 +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import sys +import time +import traceback +import re +import os +import socket +import types +import select +import xml.dom.minidom +from pyxmpp import xmlextra + +def xmldiff(node1, node2): + if node1.nodeType == node1.TEXT_NODE: + if not node2.nodeType == node2.TEXT_NODE \ + or re.compile(node2.data + "$").match(node1.data) is None: + raise Exception("data in text node " + node1.data + " does not match " + node2.data) + elif node1.nodeType == node1.DOCUMENT_NODE: + if not node2.nodeType == node2.DOCUMENT_NODE: + raise Exception("node1 is Document but not node2 (" + node2.nodeType + ")") + elif node1.tagName != node2.tagName: + raise Exception("Different tag name : " + node1.tagName + " != " + node2.tagName) + else: + for attr in node1._get_attributes().keys(): + if not node2.hasAttribute(attr) \ + or node1.getAttribute(attr) != node2.getAttribute(attr): + raise Exception("(" + node1.tagName + ") Different attributes : " + node1.getAttribute(attr) + " != " + node2.getAttribute(attr)) + if len(node1.childNodes) != len(node2.childNodes): + raise Exception("(" + node1.tagName + ") Different children number : " + str(len(node1.childNodes)) + " != " + str(len(node2.childNodes))) + for i in range(len(node1.childNodes)): + xmldiff(node1.childNodes[i], node2.childNodes[i]) + +class DummyServer: + def __init__(self, host, port, responses = None): + for res in socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): + af, socktype, proto, canonname, sa = res + try: + s = socket.socket(af, socktype, proto) + except socket.error, msg: + print >>sys.stderr, msg + s = None + raise socket.error + try: + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind(sa) + s.listen(1) + except socket.error, msg: + print >>sys.stderr, msg + s.close() + s = None + raise socket.error + break + self.socket = s + self.responses = None + self.queries = None + self.real_queries = [] + + def serve(self): + conn = None + try: + conn, addr = self.socket.accept() + rfile = conn.makefile('rb', -1) + if self.responses: + data = None + for idx in range(len(self.responses)): + # if response is a function apply it (it must return a string) + # it is given previous received data + if isinstance(self.responses[idx], types.FunctionType): + response = self.responses[idx](data) + else: + response = self.responses[idx] + if response is not None: + #print >>sys.stderr, 'Sending : ', response + conn.send(response) + data = rfile.readline() + if not data: + break + else: + self.real_queries.append(data) + #print >>sys.stderr, 'Receive : ', data + if conn is not None: + conn.close() + if self.socket is not None: + self.socket.close() + self.socket = None + except: + type, value, stack = sys.exc_info() + print >>sys.stderr, "".join(traceback.format_exception + (type, value, stack, 5)) + + def verify_queries(self): + result = True + queries_len = len(self.queries) + if queries_len == len(self.real_queries): + for idx in range(queries_len): + real_query = self.real_queries[idx] + match = (re.compile(self.queries[idx], re.M).match(real_query) is not None) + if not match: + result = False + print >>sys.stderr, "Unexpected query :\n" + \ + "Expected query : _" + self.queries[idx] + "_\n" + \ + "Receive query : _" + real_query + "_\n" + else: + result = False + print >>sys.stderr, "Expected " + str(queries_len) + \ + " queries, got " + str(len(self.real_queries)) + \ + "\t" + str(self.real_queries) + return result + +class XMLDummyServer(DummyServer): + def __init__(self, host, port, responses, stream_handler): + DummyServer.__init__(self, host, port, responses) + self._reader = xmlextra.StreamReader(stream_handler) + + def serve(self): + try: + conn, addr = self.socket.accept() + if self.responses: + data = None + for idx in range(len(self.responses)): + try: + # This approximation is not clean + # received size is based on the expected size in self.queries + data = conn.recv(1024 + len(self.queries[idx])) +# print "receive : " + data + if data: + #print "-----------RECEIVE1 " + data + r = self._reader.feed(data) + except: + type, value, stack = sys.exc_info() + print "".join (traceback.format_exception + (type, value, stack, 5)) + raise + if data: + self.real_queries.append(data) + # if response is a function apply it (it must return a string) + # it is given previous received data + if isinstance(self.responses[idx], types.FunctionType): + response = self.responses[idx](data) + else: + response = self.responses[idx] + if response is not None: +# print >>sys.stderr, '---------SENDING : ', response + conn.send(response) + data = conn.recv(1024) + if data: +# print "-----------RECEIVE2 " + data + r = self._reader.feed(data) + self.real_queries.append(data) + conn.close() + self.socket.close() + self.socket = None + except: + type, value, stack = sys.exc_info() + print "".join (traceback.format_exception + (type, value, stack, 5)) + raise + + def verify_queries(self): + result = True + full_real_queries = "" + full_recv_queries = "" + for idx in range(len(self.real_queries)): + full_real_queries += self.real_queries[idx].rstrip(os.linesep) + for idx in range(len(self.queries)): + full_recv_queries += self.queries[idx].rstrip(os.linesep) + # Do not receive it but add it so that xml parsing can succeed + #full_real_queries += "" + real_query = xml.dom.minidom.parseString(full_real_queries) + recv_query = xml.dom.minidom.parseString(full_recv_queries) + try: + utils.xmldiff(real_query, recv_query) + except Exception, msg: + result = False + print >>sys.stderr, msg + return result + +def test(): + server = DummyServer(("localhost", 4242)) + server.responses = ["rep1\n", "rep2\n"] + server.serve() + +if __name__ == '__main__': + test() --- /dev/null +++ jmc-0.3b3/src/jmc/jabber/tests/disco.py @@ -0,0 +1,83 @@ +## +## disco.py +## Login : David Rousselie +## Started on Sun Jul 8 20:59:32 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2007 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import unittest + +from jmc.jabber.disco import MailRootDiscoGetInfoHandler, \ + IMAPAccountDiscoGetInfoHandler +from jmc.lang import Lang + +class MockDiscoIndentity(object): + def __init__(self): + self.category = "" + self.type = "" + +class MockAccountManager(object): + def __init__(self): + self.has_multiple_account_type = False + +class MockComponent(object): + def __init__(self): + self.name = "" + self.disco_identity = MockDiscoIndentity() + self.account_manager = MockAccountManager() + +class MailRootDiscoGetInfoHandler_TestCase(unittest.TestCase): + def test_root_disco_get_info(self): + component = MockComponent() + component.name = "Mock component" + component.disco_identity.category = "gateway" + component.disco_identity.type = "smtp" + component.account_manager.has_multiple_account_type = True + handler = MailRootDiscoGetInfoHandler(component) + # stanza, lang_class, node, disco_obj, data + disco_infos = handler.handle(None, None, None, None, None) + self.assertTrue(disco_infos[0].has_feature("jabber:iq:gateway")) + self.assertTrue(disco_infos[0].has_feature("http://jabber.org/protocol/disco#info")) + self.assertTrue(disco_infos[0].has_feature("http://jabber.org/protocol/disco#items")) + self.assertTrue(disco_infos[0].has_feature("http://jabber.org/protocol/commands")) + self.assertEquals(len(disco_infos[0].get_identities()), 2) + self.assertTrue(disco_infos[0].identity_is("gateway", "smtp")) + self.assertTrue(disco_infos[0].identity_is("headline", "newmail")) + +class IMAPAccountDiscoGetInfoHandler_TestCase(unittest.TestCase): + def test_handle_not_imap(self): + component = MockComponent() + component.name = "Mock component" + component.disco_identity.category = "gateway" + component.disco_identity.type = "smtp" + component.account_manager.has_multiple_account_type = True + handler = IMAPAccountDiscoGetInfoHandler(component) + # stanza, lang_class, node, disco_obj, data + disco_infos = handler.handle(None, Lang.en, "account@jmc.test.com/POP3", + None, None) + self.assertTrue(disco_infos[0].has_feature("jabber:iq:register")) + self.assertFalse(disco_infos[0].has_feature("http://jabber.org/protocol/commands")) + +def suite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(MailRootDiscoGetInfoHandler_TestCase, 'test')) + suite.addTest(unittest.makeSuite(IMAPAccountDiscoGetInfoHandler_TestCase, 'test')) + return suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/jabber/tests/component.py @@ -0,0 +1,1584 @@ + + +# -*- coding: utf-8 -*- +## +## test_component.py +## Login : +## Started on Wed Feb 14 18:04:49 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2007 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import unittest +import sys +import time +import logging +import time + +from sqlobject import * +from sqlobject.dbconnection import TheURIOpener + +from pyxmpp.presence import Presence +from pyxmpp.message import Message +from pyxmpp.iq import Iq + +from jcl.tests import JCLTestCase +import jcl.model as model +from jcl.model import account +from jcl.model.account import Account, PresenceAccount, LegacyJID, User +from jcl.jabber.tests.presence import DefaultSubscribeHandler_TestCase, \ + DefaultUnsubscribeHandler_TestCase +from jcl.jabber.tests.feeder import FeederMock, SenderMock + +from jmc.model.account import MailAccount, IMAPAccount, POP3Account, \ + GlobalSMTPAccount, AbstractSMTPAccount, SMTPAccount, NoAccountError +from jmc.jabber import MailHandler +from jmc.jabber.message import SendMailMessageHandler +from jmc.jabber.presence import MailSubscribeHandler, \ + MailUnsubscribeHandler, MailPresenceHandler +from jmc.jabber.component import MailComponent, MailFeederHandler, \ + MailSender +from jmc.lang import Lang + +if sys.platform == "win32": + DB_PATH = "/c|/temp/jmc_test.db" +else: + DB_PATH = "/tmp/jmc_test.db" +DB_URL = DB_PATH# + "?debug=1&debugThreading=1" + +class MockStream(object): + def __init__(self, + jid="", + secret="", + server="", + port="", + keepalive=True): + self.sent = [] + self.connection_started = False + self.connection_stopped = False + self.eof = False + self.socket = [] + + def send(self, iq): + self.sent.append(iq) + + def set_iq_set_handler(self, iq_type, ns, handler): + if not iq_type in ["query"]: + raise Exception("IQ type unknown: " + iq_type) + if not ns in ["jabber:iq:version", + "jabber:iq:register", + "http://jabber.org/protocol/disco#items", + "http://jabber.org/protocol/disco#info"]: + raise Exception("Unknown namespace: " + ns) + if handler is None: + raise Exception("Handler must not be None") + + set_iq_get_handler = set_iq_set_handler + + def set_presence_handler(self, status, handler): + if not status in ["available", + "unavailable", + "probe", + "subscribe", + "subscribed", + "unsubscribe", + "unsubscribed"]: + raise Exception("Status unknown: " + status) + if handler is None: + raise Exception("Handler must not be None") + + def set_message_handler(self, msg_type, handler): + if not msg_type in ["normal"]: + raise Exception("Message type unknown: " + msg_type) + if handler is None: + raise Exception("Handler must not be None") + + def connect(self): + self.connection_started = True + + def disconnect(self): + self.connection_stopped = True + + def loop_iter(self, timeout): + time.sleep(timeout) + + def close(self): + pass + +class MockMailAccount(object): + def _init(self): + self.connected = False + self.has_connected = False + self.marked_all_as_read = False + self._action = PresenceAccount.DO_NOTHING + + def connect(self): + self.connected = True + self.has_connected = True + + def mark_all_as_read(self): + self.marked_all_as_read = True + + def disconnect(self): + self.connected = False + + def get_action(self): + return self._action + + action = property(get_action) + +class MockIMAPAccount(MockMailAccount, IMAPAccount): + def _init(self, *args, **kw): + IMAPAccount._init(self, *args, **kw) + MockMailAccount._init(self) + self.get_mail_list_summary_called = False + + def ls_dir(self, imap_dir): + if imap_dir == "": + return ["INBOX"] + elif imap_dir == "INBOX": + return ["dir1", "dir2"] + elif imap_dir == "INBOX/dir1": + return ["subdir1", "subdir2"] + return [] + + def get_mail_with_attachment_list(self): + return [("1", "mail 1"), + ("2", "mail 2")] + + def get_mail_list_summary(self, start_index=1, end_index=20): + if self.get_mail_list_summary_called: + return [("11", "mail 11"), + ("12", "mail 12"), + ("13", "mail 13"), + ("14", "mail 14"), + ("15", "mail 15"), + ("16", "mail 16"), + ("17", "mail 17"), + ("18", "mail 18"), + ("19", "mail 19"), + ("20", "mail 20")] + else: + self.get_mail_list_summary_called = True + return [("1", "mail 1"), + ("2", "mail 2"), + ("3", "mail 3"), + ("4", "mail 4"), + ("5", "mail 5"), + ("6", "mail 6"), + ("7", "mail 7"), + ("8", "mail 8"), + ("9", "mail 9"), + ("10", "mail 10")] + + +class MockPOP3Account(MockMailAccount, POP3Account): + def _init(self, *args, **kw): + POP3Account._init(self, *args, **kw) + MockMailAccount._init(self) + +class MailComponent_TestCase(JCLTestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[Account, PresenceAccount, User, + MailAccount, IMAPAccount, POP3Account, + GlobalSMTPAccount, + AbstractSMTPAccount, SMTPAccount, + MockIMAPAccount, MockPOP3Account]) + self.comp = MailComponent("jmc.test.com", + "password", + "localhost", + "5347", + None, + None) + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + + def _account_has_been_checked(self, _account, old_value): + if old_value == _account.lastcheck: + return False + else: + delta = int(time.time()) - _account.lastcheck + return (delta <= 1) and (delta >= 0) + + ########################################################################### + # 'feed' test methods + ########################################################################### + def test_feed_first_check(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.status = account.ONLINE + self.assertTrue(account11.first_check) + self.assertEquals(account11.error, None) + self.assertFalse(account11.waiting_password_reply) + account11.live_email_only = False + account11.lastcheck = 0 + account11.password = "" + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(len(result), 0) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 0) + self.assertFalse(account11.first_check) + self.assertFalse(account11.waiting_password_reply) + self.assertEquals(account11.error, None) + self.assertFalse(account11.connected) + self.assertFalse(account11.has_connected) + self.assertFalse(account11.marked_all_as_read) + self.assertTrue(self._account_has_been_checked(account11, + 0)) + + def test_feed_live_email_init_no_password(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.status = account.ONLINE + self.assertTrue(account11.first_check) + self.assertEquals(account11.error, None) + self.assertFalse(account11.waiting_password_reply) + account11.live_email_only = True + account11.password = None + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(len(result), 0) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 1) + self.assertEquals(sent[0].get_to(), "test1@test.com") + self.assertEquals(sent[0].get_from(), "account11@jmc.test.com") + self.assertTrue(account11.first_check) + self.assertTrue(account11.waiting_password_reply) + self.assertEquals(account11.error, None) + self.assertFalse(account11.connected) + self.assertFalse(account11.has_connected) + self.assertFalse(account11.marked_all_as_read) + + def test_feed_live_email_init_no_password2(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.status = account.ONLINE + self.assertTrue(account11.first_check) + self.assertEquals(account11.error, None) + account11.waiting_password_reply = True + account11.live_email_only = True + account11.password = None + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(result, []) + self.assertTrue(account11.first_check) + self.assertTrue(account11.waiting_password_reply) + self.assertEquals(account11.error, None) + self.assertFalse(account11.connected) + self.assertFalse(account11.has_connected) + self.assertFalse(account11.marked_all_as_read) + self.assertEquals(len(self.comp.stream.sent), 0) + + def test_feed_interval_no_check(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = PresenceAccount.DO_NOTHING + account11.first_check = False + account11.lastcheck = old_value = int(time.time()) - 2 + account11.interval = 2 + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(result, []) + self.assertFalse(self._account_has_been_checked(account11, + old_value)) + + def test_feed_interval_first_check(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = PresenceAccount.DO_NOTHING + account11.first_check = True + account11.lastcheck = 0 + account11.interval = 2 + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(result, []) + self.assertTrue(self._account_has_been_checked(account11, 0)) + + def test_feed_interval_check(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = PresenceAccount.DO_NOTHING + account11.first_check = False + account11.lastcheck = 0 + account11.interval = 2 + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(result, []) + self.assertTrue(self._account_has_been_checked(account11, 0)) + + def test_feed_no_password(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = MailAccount.RETRIEVE + account11.status = account.ONLINE + account11.first_check = False + account11.lastcheck = 0 + account11.interval = 2 + account11.password = None + self.assertFalse(account11.waiting_password_reply) + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(account11.error, None) + self.assertEquals(len(result), 0) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 1) + self.assertEquals(sent[0].get_to(), "test1@test.com") + self.assertEquals(sent[0].get_from(), "account11@jmc.test.com") + self.assertTrue(self._account_has_been_checked(account11, 0)) + self.assertFalse(account11.connected) + self.assertFalse(account11.has_connected) + + def test_feed_unknown_action(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = 42 # Unknown action + account11.status = account.ONLINE + account11.first_check = False + account11.lastcheck = 0 + account11.interval = 2 + account11.password = "password" + account11.get_new_mail_list = lambda: [] + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertNotEquals(account11.error, None) + self.assertEquals(len(result), 0) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 2) + self.assertEquals(sent[0].get_to(), "test1@test.com") + self.assertEquals(sent[0].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[1].get_to(), "test1@test.com") + self.assertEquals(sent[1].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[1].xmlnode.name, "presence") + self.assertEquals(sent[1].xmlnode.children.name, "show") + self.assertEquals(sent[1].xmlnode.children.content, "dnd") + self.assertTrue(self._account_has_been_checked(account11, 0)) + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + + def test_feed_retrieve_no_mail(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = MailAccount.RETRIEVE + account11.status = account.ONLINE + account11.first_check = False + account11.lastcheck = 0 + account11.interval = 2 + account11.password = "password" + account11.get_new_mail_list = lambda: [] + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(account11.error, None) + self.assertEquals(result, []) + self.assertTrue(self._account_has_been_checked(account11, 0)) + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + self.assertEquals(len(self.comp.stream.sent), 0) + + def test_feed_cancel_error(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = MailAccount.RETRIEVE + account11.status = account.DND + account11.error = "An error" + account11.first_check = False + account11.lastcheck = 0 + account11.interval = 2 + account11.password = "password" + account11.get_new_mail_list = lambda: [] + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(account11.error, None) + self.assertEquals(result, []) + self.assertTrue(self._account_has_been_checked(account11, 0)) + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 1) + self.assertEquals(sent[0].get_to(), "test1@test.com") + self.assertEquals(sent[0].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[0].xmlnode.name, "presence") + self.assertEquals(sent[0].xmlnode.children.name, "show") + self.assertEquals(sent[0].xmlnode.children.content, "online") + + def test_feed_retrieve_mail(self): + def mock_get_mail(index): + return [("body1", "from1@test.com"), + ("body2", "from2@test.com")][index] + model.db_connect() + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = MailAccount.RETRIEVE + account11.status = account.ONLINE + account11.first_check = False + account11.lastcheck = 0 + account11.interval = 2 + account11.password = "password" + account11.get_new_mail_list = lambda: [0, 1] + account11.get_mail = mock_get_mail + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(account11.error, None) + self.assertTrue(self._account_has_been_checked(account11, 0)) + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertEquals(len(result), 2) + self.assertEquals(result[0][0], + "from1@test.com") + self.assertEquals(result[0][1], + account11.default_lang_class.new_mail_subject \ + % ("from1@test.com")) + self.assertEquals(result[0][2], "body1") + self.assertEquals(result[1][0], + "from2@test.com") + self.assertEquals(result[1][1], \ + account11.default_lang_class.new_mail_subject \ + % ("from2@test.com")) + self.assertEquals(result[1][2], "body2") + model.db_disconnect() + + def test_feed_digest_no_mail(self): + model.db_connect() + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = MailAccount.DIGEST + account11.status = account.ONLINE + account11.first_check = False + account11.lastcheck = 0 + account11.interval = 2 + account11.password = "password" + account11.get_new_mail_list = lambda: [] + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(account11.error, None) + self.assertEquals(result, []) + self.assertTrue(self._account_has_been_checked(account11, 0)) + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + self.assertEquals(len(self.comp.stream.sent), 0) + model.db_disconnect() + + def test_feed_digest_mail(self): + def mock_get_mail_summary(index): + return [("body1", "from1@test.com"), + ("body2", "from2@test.com")][index] + model.db_connect() + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11._action = MailAccount.DIGEST + account11.status = account.ONLINE + account11.first_check = False + account11.lastcheck = 0 + account11.interval = 2 + account11.password = "password" + account11.get_new_mail_list = lambda: [0, 1] + account11.get_mail_summary = mock_get_mail_summary + result = self.comp.tick_handlers[0].feeder.feed(account11) + self.assertEquals(account11.error, None) + self.assertTrue(self._account_has_been_checked(account11, 0)) + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertEquals(len(result), 1) + self.assertEquals(result[0][1], + account11.default_lang_class.new_digest_subject \ + % (2)) + self.assertEquals(result[0][2], + "body1\n----------------------------------\nbody2\n----------------------------------\n") + model.db_disconnect() + + ########################################################################### + # 'initialize_live_email' test methods + ########################################################################### + def test_initialize_live_email(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.status = account.ONLINE + self.assertTrue(account11.first_check) + self.assertEquals(account11.error, None) + account11.live_email_only = True + account11.password = "password" + continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11) + self.assertEquals(continue_checking, True) + self.assertFalse(account11.first_check) + self.assertFalse(account11.waiting_password_reply) + self.assertEquals(account11.error, None) + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + self.assertTrue(account11.marked_all_as_read) + + def test_initialize_live_email_connection_error(self): + def raiser(): + raise Exception + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.connect = raiser + account11.status = account.ONLINE + self.assertTrue(account11.first_check) + self.assertEquals(account11.error, None) + account11.live_email_only = True + account11.password = "password" + continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11) + self.assertEquals(continue_checking, False) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 2) + self.assertEquals(sent[0].get_to(), "test1@test.com") + self.assertEquals(sent[0].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[1].get_to(), "test1@test.com") + self.assertEquals(sent[1].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[1].xmlnode.name, "presence") + self.assertEquals(sent[1].xmlnode.children.name, "show") + self.assertEquals(sent[1].xmlnode.children.content, "dnd") + self.assertTrue(account11.first_check) + self.assertFalse(account11.waiting_password_reply) + self.assertEquals(account11.error, "") + self.assertFalse(account11.connected) + self.assertFalse(account11.has_connected) + self.assertFalse(account11.marked_all_as_read) + + def test_initialize_live_email_mark_as_read_error(self): + def raiser(): + raise Exception + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.mark_all_as_read = raiser + account11.status = account.ONLINE + self.assertTrue(account11.first_check) + self.assertEquals(account11.error, None) + account11.live_email_only = True + account11.password = "password" + continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11) + self.assertEquals(continue_checking, False) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 2) + self.assertEquals(sent[0].get_to(), "test1@test.com") + self.assertEquals(sent[0].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[1].get_to(), "test1@test.com") + self.assertEquals(sent[1].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[1].xmlnode.name, "presence") + self.assertEquals(sent[1].xmlnode.children.name, "show") + self.assertEquals(sent[1].xmlnode.children.content, "dnd") + self.assertTrue(account11.first_check) + self.assertFalse(account11.waiting_password_reply) + self.assertEquals(account11.error, "") + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + self.assertFalse(account11.marked_all_as_read) + + def test_initialize_live_email_disconnection_error(self): + def raiser(): + raise Exception + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.disconnect = raiser + account11.status = account.ONLINE + self.assertTrue(account11.first_check) + self.assertEquals(account11.error, None) + account11.live_email_only = True + account11.password = "password" + continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11) + self.assertFalse(continue_checking) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 2) + self.assertEquals(sent[0].get_to(), "test1@test.com") + self.assertEquals(sent[0].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[1].get_to(), "test1@test.com") + self.assertEquals(sent[1].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[1].xmlnode.name, "presence") + self.assertEquals(sent[1].xmlnode.children.name, "show") + self.assertEquals(sent[1].xmlnode.children.content, "dnd") + self.assertEquals(continue_checking, False) + self.assertTrue(account11.first_check) + self.assertFalse(account11.waiting_password_reply) + self.assertEquals(account11.error, "") + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + self.assertTrue(account11.marked_all_as_read) + + def test_initialize_live_email_cancel_error(self): + account11 = MockIMAPAccount(user=User(jid="test1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.status = account.DND + account11.error = "An error" + self.assertTrue(account11.first_check) + account11.live_email_only = True + account11.password = "password" + continue_checking = self.comp.tick_handlers[0].feeder.initialize_live_email(account11) + self.assertEquals(continue_checking, True) + self.assertFalse(account11.first_check) + self.assertFalse(account11.waiting_password_reply) + self.assertEquals(account11.error, None) + self.assertFalse(account11.connected) + self.assertTrue(account11.has_connected) + self.assertTrue(account11.marked_all_as_read) + sent = self.comp.stream.sent + self.assertEquals(len(sent), 1) + self.assertEquals(sent[0].get_to(), "test1@test.com") + self.assertEquals(sent[0].get_from(), "account11@jmc.test.com") + self.assertEquals(sent[0].xmlnode.name, "presence") + self.assertEquals(sent[0].xmlnode.children.name, "show") + self.assertEquals(sent[0].xmlnode.children.content, "online") + + def test_disco_get_info_imap_node(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + account11 = MockIMAPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="jcl.test.com/IMAP") + disco_info = self.comp.disco_get_info("IMAP", info_query) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertTrue(disco_info.has_feature("jabber:iq:register")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#items")) + + def test_disco_get_info_imap_node_no_account(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + account11 = MockPOP3Account(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account21 = MockIMAPAccount(user=User(jid="user2@test.com"), + name="account21", + jid="account21@jmc.test.com") + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="jcl.test.com/IMAP") + disco_info = self.comp.disco_get_info("IMAP", info_query) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertTrue(disco_info.has_feature("jabber:iq:register")) + self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#info")) + self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#items")) + + def test_disco_get_info_imap_long_node(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + account11 = MockIMAPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com/IMAP") + disco_info = self.comp.disco_get_info("IMAP/account11", + info_query) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertTrue(disco_info.has_feature("jabber:iq:register")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#items")) + + def test_disco_get_info_not_imap_long_node(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + account11 = MockPOP3Account(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com/POP3") + disco_info = self.comp.disco_get_info("POP3/account11", + info_query) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertTrue(disco_info.has_feature("jabber:iq:register")) + self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#info")) + self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#items")) + + def test_disco_get_info_imap_dir_node(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + account11 = MockIMAPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.mailbox = "INBOX/dir1" + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com/IMAP/INBOX") + disco_info = self.comp.disco_get_info("IMAP/account11/INBOX", + info_query) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertTrue(disco_info.has_feature("jabber:iq:register")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#items")) + + def test_disco_get_info_imap_dir_node_already_registered(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + account11 = MockIMAPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.mailbox = "INBOX" + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com/IMAP/INBOX") + disco_info = self.comp.disco_get_info("IMAP/account11/INBOX", + info_query) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertTrue(disco_info.has_feature("jabber:iq:register")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#items")) + + def test_disco_get_info_imap_dir_node_last_subdir(self): + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + account11 = MockIMAPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jmc.test.com") + account11.mailbox = "INBOX/dir1/subdir1" + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com/IMAP/INBOX/dir1/subdir1") + disco_info = self.comp.disco_get_info("IMAP/account11/INBOX/dir1/subdir1", + info_query) + self.assertEquals(len(self.comp.stream.sent), 0) + self.assertTrue(disco_info.has_feature("jabber:iq:register")) + self.assertTrue(disco_info.has_feature("http://jabber.org/protocol/disco#info")) + self.assertFalse(disco_info.has_feature("http://jabber.org/protocol/disco#items")) + + def test_disco_get_items_base_imap_account(self): + account11 = MockIMAPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jcl.test.com") + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com/IMAP") + disco_items = self.comp.disco_get_items("IMAP/account11", info_query) + self.assertEquals(len(disco_items.get_items()), 1) + disco_item = disco_items.get_items()[0] + self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid) + + "/IMAP/INBOX") + self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX") + self.assertEquals(disco_item.get_name(), "INBOX") + + def test_disco_get_items_inbox_imap_account(self): + account11 = MockIMAPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jcl.test.com") + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com/IMAP/INBOX") + disco_items = self.comp.disco_get_items("IMAP/account11/INBOX", info_query) + self.assertEquals(len(disco_items.get_items()), 2) + disco_item = disco_items.get_items()[0] + self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid) + + "/IMAP/INBOX/dir1") + self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX" + + "/dir1") + self.assertEquals(disco_item.get_name(), "dir1") + disco_item = disco_items.get_items()[1] + self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid) + + "/IMAP/INBOX/dir2") + self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX" + + "/dir2") + self.assertEquals(disco_item.get_name(), "dir2") + + def test_disco_get_items_subdir_imap_account(self): + account11 = MockIMAPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jcl.test.com") + info_query = Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account11@jcl.test.com/IMAP") + disco_items = self.comp.disco_get_items("IMAP/account11/INBOX/dir1", info_query) + self.assertEquals(len(disco_items.get_items()), 2) + disco_item = disco_items.get_items()[0] + self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid) + + "/IMAP/INBOX/dir1/subdir1") + self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX" + + "/dir1/subdir1") + self.assertEquals(disco_item.get_name(), "subdir1") + disco_item = disco_items.get_items()[1] + self.assertEquals(unicode(disco_item.get_jid()), unicode(account11.jid) + + "/IMAP/INBOX/dir1/subdir2") + self.assertEquals(disco_item.get_node(), "IMAP/" + account11.name + "/INBOX" + + "/dir1/subdir2") + self.assertEquals(disco_item.get_name(), "subdir2") + + def test_account_get_register_imap_dir_already_registered(self): + model.db_connect() + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + user1 = User(jid="user1@test.com") + account1 = MockIMAPAccount(user=user1, + name="account1", + jid="account1@jcl.test.com") + account1.mailbox = "INBOX" + account11 = MockIMAPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account11.mailbox = "INBOX/dir1" + account11.password = "pass1" + account11.port = 993 + account11.host = "host1" + account11.login = "login1" + account11.ssl = True + account11.interval = 1 + account11.store_password = False + account11.live_email_only = True + account11.chat_action = PresenceAccount.DO_NOTHING + account11.online_action = PresenceAccount.DO_NOTHING + account11.away_action = PresenceAccount.DO_NOTHING + account11.xa_action = PresenceAccount.DO_NOTHING + account11.dnd_action = PresenceAccount.DO_NOTHING + account11.offline_action = PresenceAccount.DO_NOTHING + account21 = MockIMAPAccount(user=User(jid="user2@test.com"), + name="account21", + jid="account21@jcl.test.com") + model.db_disconnect() + self.comp.handle_get_register(Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account1@jcl.test.com/IMAP/INBOX/dir1")) + self.assertEquals(len(self.comp.stream.sent), 1) + iq_sent = self.comp.stream.sent[0] + self.assertEquals(iq_sent.get_to(), "user1@test.com") + titles = iq_sent.xpath_eval("jir:query/jxd:x/jxd:title", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(titles), 1) + self.assertEquals(titles[0].content, + Lang.en.register_title) + instructions = iq_sent.xpath_eval("jir:query/jxd:x/jxd:instructions", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(instructions), 1) + self.assertEquals(instructions[0].content, + Lang.en.register_instructions) + fields = iq_sent.xpath_eval("jir:query/jxd:x/jxd:field", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(fields), 16) + field = fields[0] + self.assertEquals(field.prop("type"), "hidden") + self.assertEquals(field.prop("var"), "name") + self.assertEquals(field.prop("label"), Lang.en.account_name) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "account11") + self.assertEquals(field.children.next.name, "required") + field = fields[1] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "chat_action") + self.assertEquals(field.prop("label"), Lang.en.field_chat_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[2] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "online_action") + self.assertEquals(field.prop("label"), Lang.en.field_online_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[3] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "away_action") + self.assertEquals(field.prop("label"), Lang.en.field_away_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[4] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "xa_action") + self.assertEquals(field.prop("label"), Lang.en.field_xa_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[5] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "dnd_action") + self.assertEquals(field.prop("label"), Lang.en.field_dnd_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[6] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "offline_action") + self.assertEquals(field.prop("label"), Lang.en.field_offline_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[7] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "login") + self.assertEquals(field.prop("label"), Lang.en.field_login) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "login1") + self.assertEquals(field.children.next.name, "required") + field = fields[8] + self.assertEquals(field.prop("type"), "text-private") + self.assertEquals(field.prop("var"), "password") + self.assertEquals(field.prop("label"), Lang.en.field_password) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "pass1") + field = fields[9] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "host") + self.assertEquals(field.prop("label"), Lang.en.field_host) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "host1") + self.assertEquals(field.children.next.name, "required") + field = fields[10] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "port") + self.assertEquals(field.prop("label"), Lang.en.field_port) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "993") + field = fields[11] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "ssl") + self.assertEquals(field.prop("label"), Lang.en.field_ssl) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[12] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "store_password") + self.assertEquals(field.prop("label"), Lang.en.field_store_password) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[13] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "live_email_only") + self.assertEquals(field.prop("label"), Lang.en.field_live_email_only) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[14] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "interval") + self.assertEquals(field.prop("label"), Lang.en.field_interval) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[15] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "mailbox") + self.assertEquals(field.prop("label"), Lang.en.field_mailbox) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "INBOX/dir1") + + def test_account_get_register_imap_dir_new(self): + model.db_connect() + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + user1 = User(jid="user1@test.com") + account1 = MockIMAPAccount(user=user1, + name="account1", + jid="account1@jcl.test.com") + account1.maildir = "INBOX" + account1.password = "pass1" + account1.port = 993 + account1.host = "host1" + account1.login = "login1" + account1.ssl = True + account1.interval = 1 + account1.store_password = False + account1.live_email_only = True + account1.chat_action = PresenceAccount.DO_NOTHING + account1.online_action = PresenceAccount.DO_NOTHING + account1.away_action = PresenceAccount.DO_NOTHING + account1.xa_action = PresenceAccount.DO_NOTHING + account1.dnd_action = PresenceAccount.DO_NOTHING + account1.offline_action = PresenceAccount.DO_NOTHING + account11 = MockIMAPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account11.maildir = "INBOX/dir1" + account11.delimiter = "/" + account21 = MockIMAPAccount(user=User(jid="user2@test.com"), + name="account21", + jid="account21@jcl.test.com") + model.db_disconnect() + self.comp.handle_get_register(Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account1@jcl.test.com/IMAP/INBOX/dir1/subdir1")) + self.assertEquals(len(self.comp.stream.sent), 1) + iq_sent = self.comp.stream.sent[0] + self.assertEquals(iq_sent.get_to(), "user1@test.com") + titles = iq_sent.xpath_eval("jir:query/jxd:x/jxd:title", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(titles), 1) + self.assertEquals(titles[0].content, + Lang.en.register_title) + instructions = iq_sent.xpath_eval("jir:query/jxd:x/jxd:instructions", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(instructions), 1) + self.assertEquals(instructions[0].content, + Lang.en.register_instructions) + fields = iq_sent.xpath_eval("jir:query/jxd:x/jxd:field", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(fields), 16) + field = fields[0] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "name") + self.assertEquals(field.prop("label"), Lang.en.account_name) + self.assertEquals(field.children.name, "required") + self.assertEquals(field.children.next, None) + field = fields[1] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "chat_action") + self.assertEquals(field.prop("label"), Lang.en.field_chat_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[2] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "online_action") + self.assertEquals(field.prop("label"), Lang.en.field_online_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[3] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "away_action") + self.assertEquals(field.prop("label"), Lang.en.field_away_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[4] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "xa_action") + self.assertEquals(field.prop("label"), Lang.en.field_xa_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[5] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "dnd_action") + self.assertEquals(field.prop("label"), Lang.en.field_dnd_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[6] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "offline_action") + self.assertEquals(field.prop("label"), Lang.en.field_offline_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[7] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "login") + self.assertEquals(field.prop("label"), Lang.en.field_login) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "login1") + self.assertEquals(field.children.next.name, "required") + field = fields[8] + self.assertEquals(field.prop("type"), "text-private") + self.assertEquals(field.prop("var"), "password") + self.assertEquals(field.prop("label"), Lang.en.field_password) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "pass1") + field = fields[9] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "host") + self.assertEquals(field.prop("label"), Lang.en.field_host) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "host1") + self.assertEquals(field.children.next.name, "required") + field = fields[10] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "port") + self.assertEquals(field.prop("label"), Lang.en.field_port) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "993") + field = fields[11] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "ssl") + self.assertEquals(field.prop("label"), Lang.en.field_ssl) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[12] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "store_password") + self.assertEquals(field.prop("label"), Lang.en.field_store_password) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[13] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "live_email_only") + self.assertEquals(field.prop("label"), Lang.en.field_live_email_only) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[14] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "interval") + self.assertEquals(field.prop("label"), Lang.en.field_interval) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[15] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "mailbox") + self.assertEquals(field.prop("label"), Lang.en.field_mailbox) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "INBOX/dir1/subdir1") + + def test_account_get_register_imap_dir_new(self): + model.db_connect() + self.comp.stream = MockStream() + self.comp.stream_class = MockStream + user1 = User(jid="user1@test.com") + account1 = MockIMAPAccount(user=user1, + name="account1", + jid="account1@jcl.test.com") + account1.maildir = "INBOX" + account1.password = "pass1" + account1.port = 993 + account1.host = "host1" + account1.login = "login1" + account1.ssl = True + account1.interval = 1 + account1.store_password = False + account1.live_email_only = True + account1.chat_action = PresenceAccount.DO_NOTHING + account1.online_action = PresenceAccount.DO_NOTHING + account1.away_action = PresenceAccount.DO_NOTHING + account1.xa_action = PresenceAccount.DO_NOTHING + account1.dnd_action = PresenceAccount.DO_NOTHING + account1.offline_action = PresenceAccount.DO_NOTHING + account11 = MockIMAPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account11.maildir = "INBOX/dir1" + account11.delimiter = "." + account21 = MockIMAPAccount(user=User(jid="user2@test.com"), + name="account21", + jid="account21@jcl.test.com") + model.db_disconnect() + self.comp.handle_get_register(Iq(stanza_type="get", + from_jid="user1@test.com", + to_jid="account1@jcl.test.com/IMAP/INBOX/dir1/subdir1")) + self.assertEquals(len(self.comp.stream.sent), 1) + iq_sent = self.comp.stream.sent[0] + self.assertEquals(iq_sent.get_to(), "user1@test.com") + titles = iq_sent.xpath_eval("jir:query/jxd:x/jxd:title", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(titles), 1) + self.assertEquals(titles[0].content, + Lang.en.register_title) + instructions = iq_sent.xpath_eval("jir:query/jxd:x/jxd:instructions", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(instructions), 1) + self.assertEquals(instructions[0].content, + Lang.en.register_instructions) + fields = iq_sent.xpath_eval("jir:query/jxd:x/jxd:field", + {"jir" : "jabber:iq:register", + "jxd" : "jabber:x:data"}) + self.assertEquals(len(fields), 16) + field = fields[0] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "name") + self.assertEquals(field.prop("label"), Lang.en.account_name) + self.assertEquals(field.children.name, "required") + self.assertEquals(field.children.next, None) + field = fields[1] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "chat_action") + self.assertEquals(field.prop("label"), Lang.en.field_chat_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[2] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "online_action") + self.assertEquals(field.prop("label"), Lang.en.field_online_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[3] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "away_action") + self.assertEquals(field.prop("label"), Lang.en.field_away_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[4] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "xa_action") + self.assertEquals(field.prop("label"), Lang.en.field_xa_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[5] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "dnd_action") + self.assertEquals(field.prop("label"), Lang.en.field_dnd_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[6] + self.assertEquals(field.prop("type"), "list-single") + self.assertEquals(field.prop("var"), "offline_action") + self.assertEquals(field.prop("label"), Lang.en.field_offline_action) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[7] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "login") + self.assertEquals(field.prop("label"), Lang.en.field_login) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "login1") + self.assertEquals(field.children.next.name, "required") + field = fields[8] + self.assertEquals(field.prop("type"), "text-private") + self.assertEquals(field.prop("var"), "password") + self.assertEquals(field.prop("label"), Lang.en.field_password) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "pass1") + field = fields[9] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "host") + self.assertEquals(field.prop("label"), Lang.en.field_host) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "host1") + self.assertEquals(field.children.next.name, "required") + field = fields[10] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "port") + self.assertEquals(field.prop("label"), Lang.en.field_port) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "993") + field = fields[11] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "ssl") + self.assertEquals(field.prop("label"), Lang.en.field_ssl) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[12] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "store_password") + self.assertEquals(field.prop("label"), Lang.en.field_store_password) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "0") + field = fields[13] + self.assertEquals(field.prop("type"), "boolean") + self.assertEquals(field.prop("var"), "live_email_only") + self.assertEquals(field.prop("label"), Lang.en.field_live_email_only) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[14] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "interval") + self.assertEquals(field.prop("label"), Lang.en.field_interval) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "1") + field = fields[15] + self.assertEquals(field.prop("type"), "text-single") + self.assertEquals(field.prop("var"), "mailbox") + self.assertEquals(field.prop("label"), Lang.en.field_mailbox) + self.assertEquals(field.children.name, "value") + self.assertEquals(field.children.content, "INBOX.dir1.subdir1") + +class MailSender_TestCase(JCLTestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[Account, PresenceAccount, MailAccount, + IMAPAccount, POP3Account, User]) + + def test_create_message(self): + mail_sender = MailSender() + model.db_connect() + user1 = User(jid="test1@test.com") + account11 = IMAPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account11.online_action = MailAccount.RETRIEVE + account11.status = account.ONLINE + message = mail_sender.create_message(account11, ("from@test.com", + "subject", + "message body")) + self.assertEquals(message.get_to(), user1.jid) + model.db_disconnect() + self.assertEquals(message.get_subject(), "subject") + self.assertEquals(message.get_body(), "message body") + addresses = message.xpath_eval("add:addresses/add:address", + {"add": "http://jabber.org/protocol/address"}) + self.assertEquals(len(addresses), 1) + self.assertEquals(addresses[0].prop("type"), + "replyto") + self.assertEquals(addresses[0].prop("jid"), + "from%test.com@jmc.test.com") + + def test_create_message_missing_email_from(self): + mail_sender = MailSender() + model.db_connect() + user1 = User(jid="test1@test.com") + account11 = IMAPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account11.online_action = MailAccount.RETRIEVE + account11.status = account.ONLINE + message = mail_sender.create_message(account11, (None, + "subject", + "message body")) + self.assertEquals(message.get_to(), user1.jid) + self.assertEquals(message.get_subject(), "subject") + self.assertEquals(message.get_body(), "message body") + addresses = message.xpath_eval("add:addresses/add:address", + {"add": "http://jabber.org/protocol/address"}) + self.assertEquals(addresses, []) + + def test_create_message_digest(self): + mail_sender = MailSender() + model.db_connect() + user1 = User(jid="test1@test.com") + account11 = IMAPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account11.online_action = MailAccount.DIGEST + account11.status = account.ONLINE + message = mail_sender.create_message(account11, ("from@test.com", + "subject", + "message body")) + self.assertEquals(message.get_to(), user1.jid) + model.db_disconnect() + self.assertEquals(message.get_subject(), "subject") + self.assertEquals(message.get_body(), "message body") + self.assertEquals(message.get_type(), "headline") + +class MailHandler_TestCase(JCLTestCase): + def setUp(self, tables=[]): + self.handler = MailHandler(None) + JCLTestCase.setUp(self, tables=[Account, AbstractSMTPAccount, + GlobalSMTPAccount, SMTPAccount, User] \ + + tables) + + def test_filter(self): + model.db_connect() + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account11.default_account = True + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jcl.test.com") + message = Message(from_jid="user1@test.com", + to_jid="user2%test.com@jcl.test.com", + body="message") + accounts = self.handler.filter(message, None) + self.assertNotEquals(accounts, None) + i = 0 + for _account in accounts: + i += 1 + if i == 1: + self.assertEquals(_account.name, "account11") + self.assertEquals(i, 1) + model.db_disconnect() + + def test_filter_root(self): + model.db_connect() + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account11.default_account = True + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jcl.test.com") + message = Message(from_jid="user1@test.com", + to_jid="jcl.test.com", + body="message") + accounts = self.handler.filter(message, None) + self.assertEquals(accounts, None) + model.db_disconnect() + + def test_filter_no_default(self): + model.db_connect() + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jcl.test.com") + message = Message(from_jid="user1@test.com", + to_jid="user2%test.com@jcl.test.com", + body="message") + accounts = self.handler.filter(message, None) + self.assertNotEquals(accounts, None) + i = 0 + for _account in accounts: + i += 1 + if i == 1: + self.assertEquals(_account.name, "account11") + else: + self.assertEquals(_account.name, "account12") + self.assertEquals(i, 2) + model.db_disconnect() + + def test_filter_wrong_dest(self): + model.db_connect() + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jcl.test.com") + message = Message(from_jid="user1@test.com", + to_jid="user2test.com@jcl.test.com", + body="message") + accounts = self.handler.filter(message, None) + self.assertEquals(accounts, None) + model.db_disconnect() + + def test_filter_wrong_account(self): + model.db_connect() + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jcl.test.com") + message = Message(from_jid="user3@test.com", + to_jid="user2%test.com@jcl.test.com", + body="message") + try: + accounts = self.handler.filter(message, None) + model.db_disconnect() + except NoAccountError, e: + model.db_disconnect() + self.assertNotEquals(e, None) + else: + self.fail("No exception 'NoAccountError' catched") + +class MailPresenceHandler_TestCase(unittest.TestCase): + def setUp(self): + self.handler = MailPresenceHandler(None) + + def test_filter(self): + message = Message(from_jid="user1@test.com", + to_jid="user11%test.com@jcl.test.com", + body="message") + result = self.handler.filter(message, None) + self.assertNotEquals(result, None) + + def test_filter_wrong_dest(self): + message = Message(from_jid="user1@test.com", + to_jid="user11@jcl.test.com", + body="message") + result = self.handler.filter(message, None) + self.assertEquals(result, None) + + def test_filter_wrong_dest2(self): + message = Message(from_jid="user1@test.com", + to_jid="jcl.test.com", + body="message") + result = self.handler.filter(message, None) + self.assertEquals(result, None) + +class MailSubscribeHandler_TestCase(DefaultSubscribeHandler_TestCase, MailHandler_TestCase): + def setUp(self): + MailHandler_TestCase.setUp(self, tables=[LegacyJID]) + self.handler = MailSubscribeHandler(None) + + def test_handle(self): + model.db_connect() + account11 = SMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jcl.test.com") + presence = Presence(from_jid="user1@test.com", + to_jid="user1%test.com@jcl.test.com", + stanza_type="subscribe") + result = self.handler.handle(presence, Lang.en, [account11]) + legacy_jids = LegacyJID.select() + self.assertEquals(legacy_jids.count(), 1) + model.db_disconnect() + +class MailUnsubscribeHandler_TestCase(DefaultUnsubscribeHandler_TestCase, MailHandler_TestCase): + def setUp(self): + MailHandler_TestCase.setUp(self, tables=[LegacyJID]) + self.handler = MailUnsubscribeHandler(None) + + def test_handle(self): + model.db_connect() + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jcl.test.com") + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jcl.test.com") + account2 = SMTPAccount(user=User(jid="user2@test.com"), + name="account2", + jid="account2@jcl.test.com") + presence = Presence(from_jid="user1@test.com", + to_jid="u111%test.com@jcl.test.com", + stanza_type="unsubscribe") + legacy_jid111 = LegacyJID(legacy_address="u111@test.com", + jid="u111%test.com@jcl.test.com", + account=account11) + legacy_jid112 = LegacyJID(legacy_address="u112@test.com", + jid="u112%test.com@jcl.test.com", + account=account11) + legacy_jid121 = LegacyJID(legacy_address="u121@test.com", + jid="u121%test.com@jcl.test.com", + account=account12) + legacy_jid122 = LegacyJID(legacy_address="u122@test.com", + jid="u122%test.com@jcl.test.com", + account=account12) + legacy_jid21 = LegacyJID(legacy_address="u21@test.com", + jid="u21%test.com@jcl.test.com", + account=account2) + result = self.handler.handle(presence, Lang.en, [account11]) + legacy_jids = LegacyJID.select() + self.assertEquals(legacy_jids.count(), 4) + removed_legacy_jid = LegacyJID.select(\ + LegacyJID.q.jid == "u111%test.com@jcl.test.com") + self.assertEquals(removed_legacy_jid.count(), 0) + model.db_disconnect() + +class MailFeederHandler_TestCase(JCLTestCase): + def setUp(self): + self.handler = MailFeederHandler(FeederMock(), SenderMock()) + JCLTestCase.setUp(self, tables=[Account, PresenceAccount, MailAccount, + IMAPAccount, POP3Account, SMTPAccount, + GlobalSMTPAccount, + AbstractSMTPAccount, User]) + + def test_filter(self): + model.db_connect() + account11 = SMTPAccount(user=User(jid="user1@test.com"), + name="account11", + jid="account11@jcl.test.com") + account13 = IMAPAccount(user=User(jid="user3@test.com"), + name="account13", + jid="account13@jcl.test.com") + account12 = POP3Account(user=User(jid="user2@test.com"), + name="account12", + jid="account12@jcl.test.com") + accounts = self.handler.filter(None, None) + i = 0 + # SQLObject > 0.8 is needed + for _account in accounts: + i += 1 + if i == 1: + self.assertEquals(_account.name, "account13") + else: + self.assertEquals(_account.name, "account12") + self.assertEquals(i, 2) + model.db_disconnect() + +def suite(): + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(MailComponent_TestCase, 'test')) + test_suite.addTest(unittest.makeSuite(MailSender_TestCase, 'test')) + test_suite.addTest(unittest.makeSuite(MailHandler_TestCase, 'test')) + test_suite.addTest(unittest.makeSuite(MailUnsubscribeHandler_TestCase, 'test')) + test_suite.addTest(unittest.makeSuite(MailSubscribeHandler_TestCase, 'test')) + test_suite.addTest(unittest.makeSuite(MailPresenceHandler_TestCase, 'test')) + test_suite.addTest(unittest.makeSuite(MailFeederHandler_TestCase, 'test')) + return test_suite + +if __name__ == '__main__': + logger = logging.getLogger() + logger.addHandler(logging.StreamHandler()) + if '-v' in sys.argv: + logger.setLevel(logging.INFO) + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/jabber/tests/presence.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +## +## presence.py +## Login : +## Started on Thu Dec 6 08:19:59 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2007 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import unittest +import time + +from pyxmpp.iq import Iq + +from jcl.model.account import User, LegacyJID, Account +from jcl.tests import JCLTestCase + +from jmc.jabber.component import MailComponent +from jmc.jabber.presence import MailAccountIQLastHandler + +class MailAccountIQLastHandler_TestCase(JCLTestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[User, LegacyJID, Account]) + self.comp = MailComponent("jmc.test.com", + "password", + "localhost", + "5347", + None, None) + self.handler = MailAccountIQLastHandler(self.comp) + + def test_handle(self): + user1 = User(jid="user1@test.com") + account11 = Account(user=user1, + name="account11", + jid="account11@jcl.test.com") + account12 = Account(user=user1, + name="account12", + jid="account12@jcl.test.com") + info_query = Iq(from_jid="user1@test.com", + to_jid="account11@jcl.test.com", + stanza_type="get") + account11.lastcheck = int(time.time()) + time.sleep(1) + result = self.handler.handle(info_query, None, account11) + self.assertEquals(len(result), 1) + self.assertEquals(result[0].get_to(), "user1@test.com") + self.assertEquals(result[0].get_from(), "account11@jcl.test.com") + self.assertEquals(result[0].get_type(), "result") + self.assertNotEquals(result[0].xmlnode.children, None) + self.assertEquals(result[0].xmlnode.children.name, "query") + self.assertEquals(int(result[0].xmlnode.children.prop("seconds")), 1) + +def suite(): + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(MailAccountIQLastHandler_TestCase, 'test')) + return test_suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/jabber/tests/__init__.py @@ -0,0 +1,18 @@ +"""JMC test module""" +__revision__ = "" + +import unittest + +from jmc.jabber.tests import component, disco, command, message, presence + +def suite(): + test_suite = unittest.TestSuite() + test_suite.addTest(component.suite()) + test_suite.addTest(disco.suite()) + test_suite.addTest(command.suite()) + test_suite.addTest(message.suite()) + test_suite.addTest(presence.suite()) + return test_suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/jabber/tests/message.py @@ -0,0 +1,256 @@ +## +## message.py +## Login : +## Started on Tue Nov 6 19:00:22 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2007 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import unittest +import re + +from pyxmpp.message import Message + +from jcl.tests import JCLTestCase +from jcl.model.account import Account, User + +from jmc.model.account import GlobalSMTPAccount, AbstractSMTPAccount, \ + SMTPAccount +from jmc.jabber.message import SendMailMessageHandler, \ + RootSendMailMessageHandler +from jmc.lang import Lang + +class MockSMTPAccount(object): + def __init__(self): + self.email_sent = 0 + self.default_from = "user1@test.com" + self.email = None + + def send_email(self, email): + self.email = email + self.email_sent += 1 + + def create_email(self, from_addr, to_addr, subject, body, + other_headers=None): + return (from_addr, to_addr, subject, body, other_headers) + +class SendMailMessageHandler_TestCase(unittest.TestCase): + def setUp(self): + self.handler = SendMailMessageHandler(None) + + def test_get_email_to_headers_from_message(self): + to_regexp = re.compile("^\s*(?i)to\s*:\s*(?P.*)") + (message, to_header) = self.handler.get_email_headers_from_message(\ + "To: dest@test.com\ntest body\n", [to_regexp], ["to_email"]) + self.assertEquals(message, "test body\n") + self.assertEquals(to_header, ["dest@test.com"]) + + def test_get_email_headers_from_message(self): + to_regexp = re.compile("^\s*(?i)to\s*:\s*(?P.*)") + cc_regexp = re.compile("^\s*(?i)cc\s*:\s*(?P.*)") + bcc_regexp = re.compile("^\s*(?i)bcc\s*:\s*(?P.*)") + subject_regexp = re.compile("^\s*(?i)subject\s*:\s*(?P.*)") + (message, headers) = self.handler.get_email_headers_from_message(\ + "To: dest@test.com\nCc: cc@test.com\n" + + "Bcc: bcc@test.com\n" + + "Subject: test subject\ntest body\n", + [to_regexp, cc_regexp, bcc_regexp, subject_regexp], + ["to_email", "cc_email", "bcc_email", "subject_email"]) + self.assertEquals(message, "test body\n") + self.assertEquals(headers, ["dest@test.com", + "cc@test.com", + "bcc@test.com", + "test subject"]) + + def test_get_email_headers_from_message_unordered(self): + to_regexp = re.compile("^\s*(?i)to\s*:\s*(?P.*)") + cc_regexp = re.compile("^\s*(?i)cc\s*:\s*(?P.*)") + bcc_regexp = re.compile("^\s*(?i)bcc\s*:\s*(?P.*)") + subject_regexp = re.compile("^\s*(?i)subject\s*:\s*(?P.*)") + (message, headers) = self.handler.get_email_headers_from_message(\ + "To: dest@test.com\nCc: cc@test.com\n" + + "Bcc: bcc@test.com\n" + + "Subject: test subject\ntest body\n", + [cc_regexp, to_regexp, subject_regexp, bcc_regexp], + ["cc_email", "to_email", "subject_email", "bcc_email"]) + self.assertEquals(message, "test body\n") + self.assertEquals(headers, ["cc@test.com", + "dest@test.com", + "test subject", + "bcc@test.com"]) + + def test_handle(self): + mock_account = MockSMTPAccount() + message = Message(from_jid="user1@test.com", + to_jid="real_dest%test.com@jmc.test.com", + subject="real subject", + body="To: dest@test.com\nCc: cc@test.com\n" \ + + "Bcc: bcc@test.com\n" \ + + "Subject: test subject\ntest body\n") + result = self.handler.handle(\ + message, Lang.en, [mock_account]) + self.assertEquals(len(result), 1) + self.assertEquals(result[0].stanza_type, "message") + self.assertEquals(result[0].get_from(), "real_dest%test.com@jmc.test.com") + self.assertEquals(result[0].get_to(), "user1@test.com") + self.assertEquals(result[0].get_subject(), + Lang.en.send_mail_ok_subject) + self.assertEquals(result[0].get_body(), + Lang.en.send_mail_ok_body % \ + ("real_dest@test.com, dest@test.com")) + self.assertEquals(mock_account.email_sent, 1) + self.assertEquals(mock_account.email[0], "user1@test.com") + self.assertEquals(mock_account.email[1], "real_dest@test.com, dest@test.com") + self.assertEquals(mock_account.email[2], "real subject") + self.assertEquals(mock_account.email[3], "test body\n") + self.assertEquals(mock_account.email[4], {u"Bcc": "bcc@test.com", + u"Cc": "cc@test.com"}) + +class RootSendMailMessageHandler_TestCase(JCLTestCase): + def setUp(self): + JCLTestCase.setUp(self, tables=[Account, GlobalSMTPAccount, + AbstractSMTPAccount, + SMTPAccount, User]) + self.handler = RootSendMailMessageHandler(None) + + def test_filter(self): + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account11.default_account = True + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jmc.test.com") + message = Message(from_jid="user1@test.com", + to_jid="account11@jmc.test.com", + body="message") + accounts = self.handler.filter(message, None) + self.assertEquals(accounts.count(), 1) + + def test_filter_no_default_account(self): + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jmc.test.com") + message = Message(from_jid="user1@test.com", + to_jid="account11@jmc.test.com", + body="message") + accounts = self.handler.filter(message, None) + self.assertEquals(accounts.count(), 2) + self.assertEquals(accounts[0].name, "account11") + + def test_filter_wrong_dest(self): + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jmc.test.com") + message = Message(from_jid="user1@test.com", + to_jid="user2%test.com@jmc.test.com", + body="message") + accounts = self.handler.filter(message, None) + self.assertEquals(accounts.count(), 2) + + def test_filter_wrong_user(self): + user1 = User(jid="user1@test.com") + account11 = SMTPAccount(user=user1, + name="account11", + jid="account11@jmc.test.com") + account12 = SMTPAccount(user=user1, + name="account12", + jid="account12@jmc.test.com") + message = Message(from_jid="user2@test.com", + to_jid="account11@jmc.test.com", + body="message") + accounts = self.handler.filter(message, None) + self.assertEquals(accounts.count(), 0) + + def test_handle(self): + mock_account = MockSMTPAccount() + message = Message(from_jid="user1@test.com", + to_jid="jmc.test.com", + subject="real subject", + body="To: dest@test.com\nCc: cc@test.com\n" \ + + "Bcc: bcc@test.com\n" \ + + "Subject: test subject\ntest body\n") + result = self.handler.handle(\ + message, Lang.en, [mock_account]) + self.assertEquals(len(result), 1) + self.assertEquals(result[0].get_type(), None) + self.assertEquals(result[0].get_from(), "jmc.test.com") + self.assertEquals(result[0].get_to(), "user1@test.com") + self.assertEquals(result[0].get_subject(), + Lang.en.send_mail_ok_subject) + self.assertEquals(result[0].get_body(), + Lang.en.send_mail_ok_body % ("dest@test.com")) + self.assertEquals(mock_account.email_sent, 1) + self.assertEquals(mock_account.email[0], "user1@test.com") + self.assertEquals(mock_account.email[1], "dest@test.com") + self.assertEquals(mock_account.email[2], "real subject") + self.assertEquals(mock_account.email[3], "test body\n") + self.assertEquals(mock_account.email[4], {u"Bcc": "bcc@test.com", + u"Cc": "cc@test.com"}) + + def test_handle_email_not_found_in_header(self): + message = Message(from_jid="user1@test.com", + to_jid="jmc.test.com", + subject="message subject", + body="message body") + accounts = [MockSMTPAccount()] + result = self.handler.handle(message, Lang.en, accounts) + self.assertEquals(len(result), 1) + self.assertEquals(result[0].get_type(), "error") + self.assertEquals(result[0].get_from(), "jmc.test.com") + self.assertEquals(result[0].get_to(), "user1@test.com") + self.assertEquals(result[0].get_subject(), + Lang.en.send_mail_error_no_to_header_subject) + self.assertEquals(result[0].get_body(), + Lang.en.send_mail_error_no_to_header_body) + + def test_handle_no_jabber_subject(self): + mock_account = MockSMTPAccount() + message = Message(from_jid="user1@test.com", + to_jid="jmc.test.com", + subject="", + body="To: dest@test.com\nCc: cc@test.com\n" \ + + "Bcc: bcc@test.com\n" \ + + "Subject: test subject\ntest body\n") + message_to_send = self.handler.handle(\ + message, Lang.en, [mock_account]) + self.assertNotEquals(message_to_send, None) + self.assertEquals(mock_account.email_sent, 1) + self.assertEquals(mock_account.email[0], "user1@test.com") + self.assertEquals(mock_account.email[1], "dest@test.com") + self.assertEquals(mock_account.email[2], "test subject") + self.assertEquals(mock_account.email[3], "test body\n") + self.assertEquals(mock_account.email[4], {u"Bcc": "bcc@test.com", + u"Cc": "cc@test.com"}) + +def suite(): + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(SendMailMessageHandler_TestCase, 'test')) + test_suite.addTest(unittest.makeSuite(RootSendMailMessageHandler_TestCase, 'test')) + return test_suite + +if __name__ == '__main__': + unittest.main(defaultTest='suite') --- /dev/null +++ jmc-0.3b3/src/jmc/jabber/tests/command.py @@ -0,0 +1,595 @@ +# -*- coding: utf-8 -*- +## +## command.py +## Login : David Rousselie +## Started on Tue Oct 23 18:53:28 2007 David Rousselie +## $Id$ +## +## Copyright (C) 2007 David Rousselie +## This program 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 2 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## + +import unittest +import tempfile +from ConfigParser import ConfigParser +import os +import sys +import logging +import time + +from pyxmpp.iq import Iq +from pyxmpp.jabber.dataforms import Field +import pyxmpp.xmlextra + +import jcl.tests +from jcl.tests import JCLTestCase +from jcl.jabber.feeder import Feeder +from jcl.model.account import User, Account, PresenceAccount +from jcl.jabber.tests.command import JCLCommandManagerTestCase +import jcl.jabber.command as command +import jcl.jabber.tests.command + +from jmc.model.account import POP3Account, IMAPAccount, SMTPAccount, \ + MailAccount, GlobalSMTPAccount, AbstractSMTPAccount +from jmc.jabber.component import MailComponent +from jmc.lang import Lang +from jmc.jabber.tests.component import MockIMAPAccount +from jmc.jabber.command import MailCommandManager + +PYXMPP_NS = pyxmpp.xmlextra.COMMON_NS + +class MailCommandManagerTestCase(JCLCommandManagerTestCase): + def setUp(self, tables=[]): + tables += [POP3Account, IMAPAccount, GlobalSMTPAccount, + AbstractSMTPAccount, SMTPAccount, + MailAccount, MockIMAPAccount, User, Account, PresenceAccount] + JCLTestCase.setUp(self, tables=tables) + self.config_file = tempfile.mktemp(".conf", "jmctest", jcl.tests.DB_DIR) + self.config = ConfigParser() + self.config.read(self.config_file) + self.comp = MailComponent("jmc.test.com", + "password", + "localhost", + "5347", + self.config, + self.config_file) + self.comp.set_admins(["admin@test.com"]) + self.command_manager = MailCommandManager(self.comp, + self.comp.account_manager) + self.comp.account_manager.account_classes = (POP3Account, IMAPAccount, + GlobalSMTPAccount, + AbstractSMTPAccount, + SMTPAccount, MockIMAPAccount) + self.user1 = User(jid="test1@test.com") + self.account11 = MockIMAPAccount(user=self.user1, + name="account11", + jid="account11@" + unicode(self.comp.jid)) + self.account12 = MockIMAPAccount(user=self.user1, + name="account12", + jid="account12@" + unicode(self.comp.jid)) + self.user2 = User(jid="test2@test.com") + self.account21 = MockIMAPAccount(user=self.user2, + name="account21", + jid="account21@" + unicode(self.comp.jid)) + self.account22 = MockIMAPAccount(user=self.user2, + name="account11", + jid="account11@" + unicode(self.comp.jid)) + self.user3 = User(jid="test3@test.com") + self.account31 = MockIMAPAccount(user=self.user3, + name="account31", + jid="account31@" + unicode(self.comp.jid)) + self.account32 = MockIMAPAccount(user=self.user3, + name="account32", + jid="account32@" + unicode(self.comp.jid)) + self.info_query = Iq(stanza_type="set", + from_jid="admin@test.com", + to_jid=self.comp.jid) + self.command_node = self.info_query.set_new_content(command.COMMAND_NS, + "command") + class MockFeederHandler(Feeder): + def __init__(self, component): + Feeder.__init__(self, component) + self.checked_accounts = [] + + def feed(self, _account): + self.checked_accounts.append(_account) + assert((int(time.time()) - _account.lastcheck \ + >= (_account.interval * self.component.time_unit))) + return [] + + self.comp.tick_handlers[0].feeder = MockFeederHandler(self.comp) + + def tearDown(self): + JCLTestCase.tearDown(self) + if os.path.exists(self.config_file): + os.unlink(self.config_file) + +class MailCommandManagerForceCheckCommand_TestCase(MailCommandManagerTestCase): + """ + Test 'force-check' ad-hoc command + """ + + def setUp(self, tables=[]): + """ + Prepare data + """ + MailCommandManagerTestCase.setUp(self, tables) + self.command_node.setProp("node", "jmc#force-check") + + def test_execute_force_check(self): + self.info_query.set_from("test1@test.com") + self.info_query.set_to("account11@" + unicode(self.comp.jid)) + result = self.command_manager.apply_command_action(\ + self.info_query, + "jmc#force-check", + "execute") + result_iq = result[0].xmlnode + result_iq.setNs(None) + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + + "", + result_iq, True, test_sibling=False)) + feeder = self.comp.tick_handlers[0].feeder + self.assertEquals(len(feeder.checked_accounts), 1) + self.assertEquals(feeder.checked_accounts[0], self.account11) + + def test_execute_force_check_root_node(self): + self.info_query.set_from("test1@test.com") + result = self.command_manager.apply_command_action(\ + self.info_query, + "jmc#force-check", + "execute") + result_iq = result[0].xmlnode + result_iq.setNs(None) + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + + "" + + "" + + "" + Lang.en.command_force_check + "" + + "" + Lang.en.command_force_check_1_description + + "" + + "" + + "" + + "" + + "" + + "" + + "", + result_iq, True)) + session_id = result_iq.children.prop("sessionid") + self.assertNotEquals(session_id, None) + context_session = self.command_manager.sessions[session_id][1] + self.assertEquals(context_session["user_jids"], + ["test1@test.com"]) + + # Second step + info_query = jcl.jabber.tests.command.prepare_submit(\ + node="jmc#force-check", + session_id=session_id, + from_jid="test1@test.com", + to_jid=unicode(self.comp.jid), + fields=[Field(field_type="list-multi", + name="account_names", + values=["account11/test1@test.com", + "account12/test1@test.com"])], + action="complete") + result = self.command_manager.apply_command_action(\ + info_query, + "jmc#force-check", + "execute") + result_iq = result[0].xmlnode + result_iq.setNs(None) + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + + "", + result_iq, True, test_sibling=False)) + self.assertEquals(context_session["account_names"], + ["account11/test1@test.com", + "account12/test1@test.com"]) + feeder = self.comp.tick_handlers[0].feeder + self.assertEquals(len(feeder.checked_accounts), 2) + self.assertEquals(feeder.checked_accounts[0], self.account11) + self.assertEquals(feeder.checked_accounts[1], self.account12) + +class MailCommandManagerGetEmailCommand_TestCase(MailCommandManagerTestCase): + """ + Test 'get-email' ad-hoc command + """ + + def setUp(self, tables=[]): + """ + Prepare data + """ + MailCommandManagerTestCase.setUp(self, tables) + self.command_node.setProp("node", "jmc#get-email") + def get_email(email_index): + """ + Mock method for IMAPAccount.get_email + """ + return ("mail body " + str(email_index), + "from" + str(email_index) + "@test.com") + self.account11.__dict__["get_mail"] = get_email + + def check_step_1(self, result, options="" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "", + last_page=False): + """ + Check first step result of get-email ad-hoc command + """ + result_iq = result[0].xmlnode + result_iq.setNs(None) + xml_ref = u"" \ + + "" \ + + "" \ + + "" \ + + "" + Lang.en.command_get_email + "" \ + + "" + Lang.en.command_get_email_1_description \ + + "" \ + + "" \ + + options + if not last_page: + xml_ref += "" + xml_ref += "" + self.assertTrue(jcl.tests.is_xml_equal(xml_ref, result_iq, True)) + session_id = result_iq.children.prop("sessionid") + self.assertNotEquals(session_id, None) + self.assertTrue(self.account11.has_connected) + self.assertFalse(self.account11.connected) + self.account11.has_connected = False + return session_id + + def check_email_message(self, result_iq, index): + """ """ + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + Lang.en.mail_subject \ + % ("from" + str(index) + "@test.com") + + "" + + "mail body " + str(index) + "" + + "" + + "
" + + "" + + "", + result_iq, True, test_sibling=False)) + + def test_execute_get_email(self): + """ + Test single email retrieval + """ + self.info_query.set_from("test1@test.com") + self.info_query.set_to("account11@" + unicode(self.comp.jid)) + result = self.command_manager.apply_command_action(\ + self.info_query, + "jmc#get-email", + "execute") + session_id = self.check_step_1(result) + + # Second step + info_query = jcl.jabber.tests.command.prepare_submit(\ + node="jmc#get-email", + session_id=session_id, + from_jid="test1@test.com", + to_jid="account11@jmc.test.com", + fields=[Field(field_type="list-multi", + name="emails", + values=["1"]), + Field(field_type="boolean", + name="fetch_more", + value=False)], + action="complete") + result = self.command_manager.apply_command_action(\ + info_query, + "jmc#get-email", + "execute") + self.assertTrue(self.account11.has_connected) + self.assertFalse(self.account11.connected) + self.assertEquals(len(result), 2) + result_iq = result[0].xmlnode + result_iq.setNs(None) + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + + "" + + "" + Lang.en.command_get_email + "" + + "" + Lang.en.command_get_email_2_description + % (1) + "" + + "", + result_iq, True, test_sibling=False)) + result_iq = result[1].xmlnode + self.check_email_message(result_iq, 1) + + def test_execute_get_emails(self): + """ + Test multiple emails retrieval + """ + self.info_query.set_from("test1@test.com") + self.info_query.set_to("account11@" + unicode(self.comp.jid)) + result = self.command_manager.apply_command_action(\ + self.info_query, + "jmc#get-email", + "execute") + session_id = self.check_step_1(result) + + # Second step + info_query = jcl.jabber.tests.command.prepare_submit(\ + node="jmc#get-email", + session_id=session_id, + from_jid="test1@test.com", + to_jid="account11@jmc.test.com", + fields=[Field(field_type="list-multi", + name="emails", + values=["1", "2"]), + Field(field_type="boolean", + name="fetch_more", + value=False)], + action="complete") + result = self.command_manager.apply_command_action(\ + info_query, + "jmc#get-email", + "execute") + self.assertTrue(self.account11.has_connected) + self.assertFalse(self.account11.connected) + self.assertEquals(len(result), 3) + result_iq = result[0].xmlnode + result_iq.setNs(None) + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + + "" + + "" + Lang.en.command_get_email + "" + + "" + Lang.en.command_get_email_2_description + % (2) + "" + + "", + result_iq, True, test_sibling=False)) + result_iq = result[1].xmlnode + self.check_email_message(result_iq, 1) + result_iq = result[2].xmlnode + self.check_email_message(result_iq, 2) + + def test_execute_get_emails_multi_pages(self): + """ + Test multiple emails retrieval + """ + self.info_query.set_from("test1@test.com") + self.info_query.set_to("account11@" + unicode(self.comp.jid)) + result = self.command_manager.apply_command_action(\ + self.info_query, + "jmc#get-email", + "execute") + session_id = self.check_step_1(result) + + # Second step + info_query = jcl.jabber.tests.command.prepare_submit(\ + node="jmc#get-email", + session_id=session_id, + from_jid="test1@test.com", + to_jid="account11@jmc.test.com", + fields=[Field(field_type="list-multi", + name="emails", + values=["1", "2"]), + Field(field_type="boolean", + name="fetch_more", + value=True)], + action="complete") + result = self.command_manager.apply_command_action(\ + info_query, + "jmc#get-email", + "execute") + self.check_step_1(result, options="" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "" \ + + "") + + # Third step + info_query = jcl.jabber.tests.command.prepare_submit(\ + node="jmc#get-email", + session_id=session_id, + from_jid="test1@test.com", + to_jid="account11@jmc.test.com", + fields=[Field(field_type="list-multi", + name="emails", + values=["13", "14"]), + Field(field_type="boolean", + name="fetch_more", + value=False)], + action="complete") + result = self.command_manager.apply_command_action(\ + info_query, + "jmc#get-email", + "execute") + self.assertTrue(self.account11.has_connected) + self.assertFalse(self.account11.connected) + self.assertEquals(len(result), 5) + result_iq = result[0].xmlnode + result_iq.setNs(None) + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + + "" + + "" + Lang.en.command_get_email + "" + + "" + Lang.en.command_get_email_2_description + % (4) + "" + + "", + result_iq, True, test_sibling=False)) + result_iq = result[1].xmlnode + self.check_email_message(result_iq, 1) + result_iq = result[2].xmlnode + self.check_email_message(result_iq, 2) + result_iq = result[3].xmlnode + self.check_email_message(result_iq, 13) + result_iq = result[4].xmlnode + self.check_email_message(result_iq, 14) + + def test_execute_get_emails_last_page(self): + """ + Test that field fetch_more does not exist if number of emails < 10 + """ + class MockIMAPAccount2(MockIMAPAccount): + """ """ + def get_mail_list_summary(self, start_index=1, end_index=20): + return [("1", "mail 1"), + ("2", "mail 2")] + + get_email_func = self.account11.get_mail + MockIMAPAccount2.createTable(ifNotExists=True) + self.account11.destroySelf() + self.account11 = MockIMAPAccount2(user=self.user1, + name="account11", + jid="account11@" + unicode(self.comp.jid)) + self.account11.__dict__["get_mail"] = get_email_func + self.info_query.set_from("test1@test.com") + self.info_query.set_to("account11@" + unicode(self.comp.jid)) + result = self.command_manager.apply_command_action(\ + self.info_query, + "jmc#get-email", + "execute") + session_id = self.check_step_1(result, options="" \ + + "", + last_page=True) + self.assertTrue("fetch_more" in + self.command_manager.sessions[session_id][1]) + self.assertEquals(\ + self.command_manager.sessions[session_id][1]["fetch_more"][-1], + "0") + + # Second step + info_query = jcl.jabber.tests.command.prepare_submit(\ + node="jmc#get-email", + session_id=session_id, + from_jid="test1@test.com", + to_jid="account11@jmc.test.com", + fields=[Field(field_type="list-multi", + name="emails", + values=["1"])], + action="complete") + result = self.command_manager.apply_command_action(\ + info_query, + "jmc#get-email", + "execute") + self.assertTrue(self.account11.has_connected) + self.assertFalse(self.account11.connected) + self.assertEquals(len(result), 2) + result_iq = result[0].xmlnode + result_iq.setNs(None) + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + + "" + + "" + Lang.en.command_get_email + "" + + "" + Lang.en.command_get_email_2_description + % (1) + "" + + "", + result_iq, True, test_sibling=False)) + result_iq = result[1].xmlnode + self.check_email_message(result_iq, 1) + MockIMAPAccount2.dropTable(ifExists=True) + + def test_execute_get_email_error(self): + """ + Test single email retrieval + """ + self.info_query.set_from("test1@test.com") + self.info_query.set_to("unknown@" + unicode(self.comp.jid)) + result = self.command_manager.apply_command_action(\ + self.info_query, + "jmc#get-email", + "execute") + result_iq = result[0].xmlnode + self.assertTrue(jcl.tests.is_xml_equal(\ + u"" + + "" + + "" + + "" + + "", + result_iq, True)) + +def suite(): + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(MailCommandManagerForceCheckCommand_TestCase, 'test')) + test_suite.addTest(unittest.makeSuite(MailCommandManagerGetEmailCommand_TestCase, 'test')) + return test_suite + +if __name__ == '__main__': + if '-v' in sys.argv: + logger = logging.getLogger() + logger.addHandler(logging.StreamHandler()) + logger.setLevel(logging.INFO) + unittest.main(defaultTest='suite')