http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/container/util/src/test/resources/spamassassin_db/spam/spam8 ---------------------------------------------------------------------- diff --git a/server/container/util/src/test/resources/spamassassin_db/spam/spam8 b/server/container/util/src/test/resources/spamassassin_db/spam/spam8 deleted file mode 100644 index addf463..0000000 --- a/server/container/util/src/test/resources/spamassassin_db/spam/spam8 +++ /dev/null @@ -1,321 +0,0 @@ -From or...@imail.ru Sun Jul 15 04:56:31 2001 -Return-Path: <or...@imail.ru> -Delivered-To: y...@netnoteinc.com -Received: from cccp.co.kr (unknown [211.218.149.105]) by - mail.netnoteinc.com (Postfix) with SMTP id 789D51140BA for - <j...@netnoteinc.com>; Sun, 15 Jul 2001 03:56:28 +0000 (Eire) -Received: from imail.ru [210.14.5.95] by cccp.co.kr running [nMail 1.04 - (Windows NT/2000) SMTP Server]; Wed, 11 Jul 2001 02:41:35 +0900 -Message-Id: <00000e0836ec$00006b26$00000...@imail.ru> -To: <6...@163.net> -From: or...@imail.ru -Subject: FW: -Date: Fri, 02 Jan 1998 04:30:44 -0400 -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -X-Priority: 3 -X-Msmail-Priority: Normal -X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) - - -<HTML> -<BODY bgColor=3D#C0C0C0> - -<FONT face=3D"Arial"> -<FONT size=3D4> -<FONT color=3D"#800040"> Thank you for your interest!</FONT> -<FONT size=3D3> -<FONT color=3D"#800040"> </FONT> -<FONT color=3D"#000000"> <BR> -<BR> -Judgment Courses offers an extensive Audio training<BR> -course in </FONT> -<FONT color=3D"#0000A0"> "How to Collect Money Judgments"</FONT> -<FONT color=3D"#000000"> . </FONT> -<FONT size=3D2> -<FONT color=3D"#000000"> S6</FONT> -<FONT size=3D3> -<FONT color=3D"#000000"> <BR> -<BR> -If you are like many people, you are not even sure what a<BR> -Money Judgment is and </FONT> -<FONT color=3D"#0000A0"> why processing Money Judgments<BR> -can earn you very substantial income</FONT> -<FONT color=3D"#000000"> .<BR> -<BR> -If you ever sue a company or a person and you win then you<BR> -will have a Money Judgment against them.<BR> -<BR> -You are happy you won but you will soon find out the<BR> -shocking fact: "Its now up to you to collect on the<BR> -Judgment". The court does not require the loser to pay you.<BR> -The court will not even help you. You must trace the loser<BR> -down, find their assets, their employment, bank accounts,<BR> -real estate, stocks and bonds, etc.<BR> -<BR> -Very few people know how to find these assets or what to do<BR> -when they are found. The result is that millions of<BR> -Judgments are just sitting in files and being forgotten.<BR> -<BR> -"In 79% of the cases the winner of a Judgment never sees a<BR> -dime."<BR> -<BR> -The non-payment of judicial debt has grown to epidemic<BR> -proportions. Right now in the United States there is<BR> -between </FONT> -<FONT color=3D"#0000A0"> 200 and 300 billion dollars of uncollected Money<= -BR> -Judgment debt</FONT> -<FONT color=3D"#000000"> . For every Judgment that is paid, 5 more<BR> -Judgments take its place.<BR> -<BR> -We identified this massive market 8 years ago and have<BR> -actively pursued Judicial Judgments since. We invented this<BR> -business. We have perfected it into a well proven and solid<BR> -profession in which only a select few will be trained in the<BR> -techniques necessary to succeed.<BR> -<BR> -With our first hand experience we have built a course which<BR> -teaches you how to start your business in this new unknown<BR> -and exciting field of processing Money Judgments.<BR> -<BR> -By following the steps laid out in our course and with<BR> -reasonable effort you can become very successful in the<BR> -processing of Money Judgments.<BR> -<BR> -The income potential is substantial in this profession. </FONT> -<FONT color=3D"#0000A0"> We<BR> -have associates who have taken our course and are now<BR> -working full time making $96,000.00 to over $200,000.00 per<BR> -year. Part time associates are earning between $24,000.00<BR> -and $100,000.00 per year </FONT> -<FONT color=3D"#000000"> . Some choose to operate out of<BR> -their home and work by themselves. Others build a sizable<BR> -organization of 15 to 25 people in attractive business<BR> -offices.<BR> -<BR> -Today our company and our associates have over 126<BR> -million dollars in Money Judgments that we are currently<BR> -processing. Of this 126 million, 25 million is in the form<BR> -of joint ventures between our firm and our associates.<BR> -Joint ventures are where we make our money. We only break<BR> -even when our course is purchased. We make a 12% margin on<BR> -the reports we supply to our associates. Our reporting<BR> -capability is so extensive that government agencies, police<BR> -officers, attorneys, credit agencies etc., all come to us<BR> -for reports.<BR> -<BR> -<BR> -Many of our associates already have real estate liens in<BR> -force of between 5 million to over 15 million dollars.<BR> -Legally this means that when the properties are sold or<BR> -refinanced our associate must be paid off. The norm is 10%<BR> -interest compounded annually on unpaid Money Judgments.<BR> -Annual interest on 5 million at 10% translates to<BR> -$500,000.00 annually in interest income, not counting the<BR> -payment of the principal.<BR> -<BR> -Our associates earn half of this amount or $250,000.00 per<BR> -year. This is just for interest, not counting principle<BR> -and not counting the compounding of the interest which can<BR> -add substantial additional income. Typically companies are<BR> -sold for 10 times earnings. Just based on simple interest<BR> -an associate with 5 million in real estate liens could sell<BR> -their business for approximately 2.5 million dollars.<BR> -<BR> -</FONT> -<FONT color=3D"#0000A0"> 92% of all of our associates work out of their ho= -me; 43%<BR> -are women and 36% are part time</FONT> -<FONT color=3D"#000000"> .<BR> -<BR> -One of the benefits of working in this field is that you are<BR> -not under any kind of time frame. If you decide to take off<BR> -for a month on vacation then go. The Judgments you are<BR> -working on will be there when you return. The Judgments<BR> -are still in force, they do not disappear.<BR> -<BR> -The way we train you is non-confrontational. You use your<BR> -computer and telephone to do most of the processing. You<BR> -never confront the debtor. The debtor doesn't know who you<BR> -are. You are not a collection agency.<BR> -<BR> -Simply stated the steps to successful Money Processing<BR> -are as follows:<BR> -<BR> -Mail our recommended letter to companies and individuals<BR> -with Money Judgments. (We train you how to find out who<BR> -to write to)<BR> -<BR> -8% to 11% of the firms and people you write will call you<BR> -and ask for your help. They call you, you don't call them<BR> -unless you want to.<BR> -<BR> -You send them an agreement (supplied in the course) to<BR> -sign which splits every dollar you collect 50% to you and<BR> -50% to them. This applies no matter if the judgment is for<BR> -$2,000.00 or $2,000,000.00.<BR> -<BR> -You then go on-line to our computers to find the debtor<BR> -and their assets. We offer over 120 powerful reports to<BR> -assist you. They range from credit reports from all three<BR> -credit bureaus, to bank account locates, employment<BR> -locates, skip traces and locating stocks and bonds, etc.<BR> -The prices of our reports are very low. Typically 1/2 to<BR> -1/3 of what other firms charge. For example we charge<BR> -$6.00 for an individuals credit report when some other<BR> -companies charge $25.00.<BR> -<BR> -Once you find the debtor and their assets you file<BR> -garnishments and liens on the assets you have located.<BR> -(Standard fill in the blanks forms are included in the<BR> -course)<BR> -<BR> -When you receive the assets you keep 50% and send 50% to<BR> -the original Judgment holder.<BR> -<BR> -Once the Judgment is fully paid you mail a Satisfaction of<BR> -Judgment to the court. (Included in the course)<BR> -<BR> -Quote's from several of our students:<BR> -<BR> -Thomas in area code 516 writes us: "I just wanted to drop<BR> -you a short note thanking you for your excellent course. </FONT> -<FONT color=3D"#0000A0"> My<BR> -first week, part time, will net me 3,700.00 dollars</FONT> -<FONT color=3D"#000000"> . Your<BR> -professionalism in both the manual and the video opened<BR> -doors for me in the future. There's no stopping me now.<BR> -Recently Thomas states he has over $8,500,000 worth of<BR> -judgments he is working on.<BR> -<BR> -After only having this course for four months, Larry S. in<BR> -area code 314 stated to us: " </FONT> -<FONT color=3D"#0000A0"> I am now making $2,000.00 per<BR> -week </FONT> -<FONT color=3D"#000000"> and expect this to grow to twice this amount with= -in the<BR> -next year. I am having a ball. I have over $250,000 in<BR> -judgments I am collecting on now."<BR> -<BR> -After having our course for 7 months Larry S. in 314 stated<BR> -" </FONT> -<FONT color=3D"#0000A0"> I am now making $12,000.00</FONT> -<FONT color=3D"#000000"> per month and have approximately<BR> -$500,000.00 in judgments I am collecting on. Looks like I<BR> -will have to hire someone to help out"<BR> -<BR> -Marshal in area code 407 states to us "I feel bad, you only<BR> -charged me $259.00 for this course and it is a goldmine. I<BR> -have added 3 full time people to help me after only having<BR> -your course for 5 months"<BR> -<BR> ->From the above information and actual results you can see<BR> -why we can state the following:<BR> -<BR> -With our course you can own your own successful business.<BR> -A business which earns you substantial income now and one<BR> -which could be sold in 3-5 years, paying you enough to<BR> -retire on and travel the world. A business which is<BR> -extremely interesting to be in. A Business in which every<BR> -day is new and exciting.<BR> -<BR> -None of your days will be hum-drum. Your brain is<BR> -Challenged. A business, which protects you from Corporate<BR> -Downsizing. A business which you can start part time from<BR> -your home and later, if you so desire, you can work in full<BR> -time. A business, which is your ticket to freedom from<BR> -others telling you what to do. A business, which lets you<BR> -control your own destiny. Our training has made this happen<BR> -for many others already. Make it happen for you!<BR> -<BR> -If the above sounds interesting to you then its time for you<BR> -to talk to a real live human being, no cost or obligation<BR> -on your part.<BR> -<BR> -</FONT> -<FONT color=3D"#800040"> Please call us at 1_406_652_0194 </FONT> -<FONT color=3D"#000000"> .<BR> -<BR> -We have </FONT> -<FONT color=3D"#800040"> Customer Support staff available to you from 8:00= -am to<BR> -9:00pm (Mountain Time) 7 days a week</FONT> -<FONT color=3D"#000000"> . If you call this number<BR> -you can talk to one of our experienced Customer Support personnel.<BR> -They can answer any questions you may have - with no obligation.<BR> -Sometimes we run special pricing on our courses and combinations<BR> -of courses. When you call our Customer Support line they can let<BR> -you know of any specials we may be running. If you like what you<BR> -read and hear about our courses, then the Customer Support person<BR> -can work with you to place your order. We are very low key. We<BR> -merely give you the facts and you can then decide if you want to<BR> -work with us or not.<BR> -<BR> -Thank you for your time and interest.<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -</FONT> -<FONT face=3D"Courier New"> -<FONT size=3D2> -<FONT color=3D"#000000"> .................................................= -....................<BR> -T h i s message i s produced a n d sent out by:<BR> -Universal S.y.s.t.e.m.s.<BR> -To be dropped form our mailing list please email us at <BR> -jame...@mail.asia-links.com call us toll free at 1=3D888=3D605=3D2485<BR> -and g i v e us y o u r email a d d r e s s or w r i t e us a t:<BR> -*Central*DB*Processing, PO: Box:1200, O r a n j e s t a d, Aruba<BR> -.....................................................................<BR> -</FONT> -<FONT face=3D"Arial"> -<FONT size=3D3> -<FONT color=3D"#000000"> <BR> -<BR> -</FONT> -<FONT size=3D3> -<FONT color=3D"#000000"> <BR> -<BR> -</FONT> -<FONT size=3D3> -<FONT color=3D"#000000"> <BR> -<BR> -<BR> -<BR> -<BR> -</FONT> -<FONT size=3D2> -<FONT color=3D"#000000"> <BR> -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''= -'''''''''''<BR> -</FONT> -<FONT size=3D3> -<FONT color=3D"#000000"> <BR> -</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FO= -NT></FONT></FONT></BODY></HTML> - - - -
http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/container/util/src/test/resources/spamassassin_db/spam/spam9 ---------------------------------------------------------------------- diff --git a/server/container/util/src/test/resources/spamassassin_db/spam/spam9 b/server/container/util/src/test/resources/spamassassin_db/spam/spam9 deleted file mode 100644 index 163bde8..0000000 --- a/server/container/util/src/test/resources/spamassassin_db/spam/spam9 +++ /dev/null @@ -1,142 +0,0 @@ -From spamassassin-sightings-ad...@lists.sourceforge.net Tue Jul 2 13:04:23 2002 -Return-Path: <spamassassin-sightings-ad...@example.sourceforge.net> -Delivered-To: y...@localhost.labs.netnoteinc.com -Received: from localhost (localhost [127.0.0.1]) - by phobos.labs.netnoteinc.com (Postfix on SuSE Linux 8.0 (i386)) with ESMTP id BB16E14F914 - for <jm@localhost>; Tue, 2 Jul 2002 12:56:51 +0100 (IST) -Received: from dogma.slashnull.org [212.17.35.15] - by localhost with IMAP (fetchmail-5.9.0) - for jm@localhost (single-drop); Tue, 02 Jul 2002 12:56:51 +0100 (IST) -Received: from usw-sf-list2.sourceforge.net (usw-sf-fw2.sourceforge.net - [216.136.171.252]) by dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id - g61Iat611966 for <jm-sa-sighti...@jmason.org>; Mon, 1 Jul 2002 19:36:56 - +0100 -Received: from usw-sf-list1-b.sourceforge.net ([10.3.1.13] - helo=usw-sf-list1.sourceforge.net) by usw-sf-list2.sourceforge.net with - esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17P62B-0000rw-00; Mon, - 01 Jul 2002 11:36:23 -0700 -Received: from [64.86.155.148] (helo=ok61655.com) by - usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id - 17P60P-0006ds-00 for <spamassassin-sighti...@lists.sourceforge.net>; - Mon, 01 Jul 2002 11:34:34 -0700 -From: "MR.DOUGLAS AND PRINCESS M." <douglassmith2...@yahoo.co.uk> -Reply-To: princessmar...@yahoo.com -To: spamassassin-sighti...@example.sourceforge.net -X-Mailer: Microsoft Outlook Express 5.00.2919.6900 DM -MIME-Version: 1.0 -Message-Id: <e17p60p-0006ds...@usw-sf-list1.sourceforge.net> -Subject: [SA] URGENT HELP.............. -Sender: spamassassin-sightings-ad...@example.sourceforge.net -Errors-To: spamassassin-sightings-ad...@example.sourceforge.net -X-Beenthere: spamassassin-sighti...@example.sourceforge.net -X-Mailman-Version: 2.0.9-sf.net -Precedence: bulk -List-Help: <mailto:spamassassin-sightings-requ...@example.sourceforge.net?subject=help> -List-Post: <mailto:spamassassin-sighti...@example.sourceforge.net> -List-Subscribe: <https://example.sourceforge.net/lists/listinfo/spamassassin-sightings>, - <mailto:spamassassin-sightings-requ...@lists.sourceforge.net?subject=subscribe> -List-Id: <spamassassin-sightings.example.sourceforge.net> -List-Unsubscribe: <https://example.sourceforge.net/lists/listinfo/spamassassin-sightings>, - <mailto:spamassassin-sightings-requ...@lists.sourceforge.net?subject=unsubscribe> -List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=spamassassin-sightings> -X-Original-Date: Mon, 5 Apr 1999 20:38:02 +0100 -Date: Mon, 5 Apr 1999 20:38:02 +0100 -Content-Type: multipart/mixed; boundary="===_SecAtt_000_1fnapngoonxcrm" - ---===_SecAtt_000_1fnapngoonxcrm -Content-Type: text/plain; charset="us-ascii" -Content-Transfer-Encoding: quoted-printable - - -DEAR SIR=2C -URGENT AND CONFIDENTIAL=3A - -Re=3ATransfer of $50=2C000=2E000=2E00 USD=5BFIFTY MILLION UNITED -STATES DOLLARS=5D=2E - -WE WANT TO TRANSFER TO OVERSEAS=5B$50=2C000=2E000=2E00=5BFIFTY -MILLION UNITED STATES DOLLARS=5DFROM A SECURITY COMPANY -IN SPAIN=2CI WANT TO ASK YOU TO QUIETLY LOOK FOR A -RELIABLE AND HONEST PERSON WHO WILL BE CAPABLE AND FIT -TO PROVIDE EITHER AN EXISTING BANK ACCOUNT OR TO SET -UP A NEW BANK ACCOUNT IMMEDIATELY TO RECEIVE THIS -MONEY=2CEVEN AN EMPTY ACCOUNT CAN SERVE TO RECEIVE THIS -MONEY=2CAS LONG AS YOU WILL REMAIN HONEST TO ME TILL THE -END OF THIS IMPORTANT BUSINESS TRANSACTION=2EI WANT TO -BELIEVE THAT YOU WILL NEVER LET ME DOWN EITHER NOW OR -IN FUTURE=2E - -I AM DOUGLAS SMITH=2CTHE AUDITOR GENERAL OF MAGNUM TRUST -INC=2E MADRID SPAIN DURING THE COURSE OF OUR AUDITING=2CI DISCOVERED A -FLOATING FUND IN AN ACCOUNT OPENED IN THE SECURITY -COMPANY IN 1990 AND SINCE 1993 NOBODY HAS OPERATED ON -THIS ACCOUNT AGAIN=2C AFTER GOING THROUGH SOME OLD FILES -IN THE RECORDS I DISCOVERED THAT THE OWNER OF THE -ACCOUNT DIED WITHOUT A HEIR HENCE THE MONEY IS -FLOATING AND IF I DO NOT REMIT THIS MONEY OUT -URGENTLY=2CIT WILL BE FORFEITED FOR NOTHING=2E - -THE OWNER OF THIS ACCOUNT WAS =22MR=2EALLAN P=2E SEAMAN=22=2CA FOREIGNER AND AN INDUSTRIALIST=2CAND HE DIED SINCE 1993 AND NO OTHER PERSON KNOWS ABOUT THIS ACCOUNT OR ANYTHING CONCERNING IT=2CTHE ACCOUNT HAS NO BENEFICIARY AND MY INVESTIGATION PROVED TO ME AS WELL THAT ALLAN=2EP SEAMAN UNTILL HIS DEATH WAS THE MANAGER DIAMOND SAFARI=5BPTY=5DS=2EA=2E - -WE WILL START THE FIRST TRANSFER WITH $20 MILLION -DOLLARS=5BTWENTY MILLION DOLLARS=5DUPON SUCCESSFUL -TRANSFER WITHOUT ANY DISAPPOINTMENT FROM YOUR SIDE=2CWE -SHALL RE-APPLY FOR THE TRANSFER OF THE REMAINING $30 -MILLION USA DOLLARS=5BTHIRTY MILLION UNITED STATES -DOLLARS=5DINTO YOUR ACCOUNT BRINGING THE SUM TOTAL TO -$50=2C000=2E000=2E00=5BFIFTY MILLION DOLLARS=5D=2E - -I AM CONTACTING YOU AS A FOREIGNER BECAUSE THIS MONEY -CAN ONLY BE APPROVED TO A FOREIGNER WITH VALID -INTERNATIONAL PASSPORT=2CDRIVERS LICENCE AND FOREIGN -ACCOUNT BECAUSE THE MONEY IS IN USA DOLLARS AND THE -FORMER OWNER OF THE ACCOUNT=22MR=2EALLAN P=2ESEAMAN IS A -FOREIGNER=2EI WILL LIKE US TO MEET FACE TO FACE TO SIGN -A BINDING AGREEMENT THAT WILL BIND US TOGETHER IN THE -BUSINESS=2CI AM REVEALING ALL THESE TO YOU WITH THE -BELIEF THAT YOU WILL NEVER LET ME DOWN IN THIS -BUSINESS=2CYOU ARE THE FIRST AND ONLY PERSON I AM -CONTACTING FOR THE BUSINESS=2CSO PLEASE REPLY URGENTLY -FOR ME TO TELL YOU THE NEXT STEP TO TAKE=2EYOU SHOULD -FORWARD YOUR TELEPHONE AND FAX NUMBERS AND YOUR BANK -ACCOUNT DETAILS THAT WILL BE USED IN TRANSFERING THE -MONEY=2E - -YOU WILL HAVE TO GIVE ME THE ASSURANCE WHEN WE -MEET THAT THIS MONEY WILL BE INTACT PENDING OUR -PHYSICAL ARRIVAL IN YOUR COUNTRY FOR SHARING AND -DISBURSEMENT OF THE FUND WHICH WILL BE 35% FOR YOUR -ASSISTANCE=2C60% WILL BE FOR US WHILE 5% WILL BE SET -ASIDE TO TAKE CARE OF ALL THE EXPENSES THAT WILL BE -INCURRED BY BOTH PARTIES DURING THE COURSE OF THE -TRANSFER=2E - -I LOOK FORWARD TO YOUR EARLIEST RESPONSE=2CALL -CORRESPONDENCE FOR NOW SHOULD BE EMAIL FOR SECURITY -REASONS=2E - -BEST REGARDS=2E - -DOUGLAS SMITH =28PLEASE CONTACT ME THROUGH MY WIFE EMAIL=28princessmar001=40yahoo=2Ecom=29FOR CONFIDENCAIL - - - ---===_SecAtt_000_1fnapngoonxcrm -Content-Type: application/octet-stream; name="aaaaaaa.txt" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="aaaaaaa.txt" - - ---===_SecAtt_000_1fnapngoonxcrm - - - -------------------------------------------------------- -This sf.net email is sponsored by:ThinkGeek -Welcome to geek heaven. -http://thinkgeek.com/sf -_______________________________________________ -Spamassassin-Sightings mailing list -spamassassin-sighti...@lists.sourceforge.net -https://lists.sourceforge.net/lists/listinfo/spamassassin-sightings - http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java ---------------------------------------------------------------------- diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java index cad6813..1f33b14 100644 --- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java +++ b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java @@ -38,10 +38,10 @@ import org.apache.james.mailets.configuration.CommonProcessors; import org.apache.james.mailets.configuration.MailetConfiguration; import org.apache.james.mailets.configuration.MailetContainer; import org.apache.james.mailets.configuration.ProcessorConfiguration; +import org.apache.james.spamassassin.SpamAssassinResult; import org.apache.james.transport.matchers.All; import org.apache.james.util.docker.Images; import org.apache.james.util.docker.SwarmGenericContainer; -import org.apache.james.util.scanner.SpamAssassinResult; import org.apache.james.utils.DataProbeImpl; import org.apache.james.utils.IMAPMessageReader; import org.apache.james.utils.SMTPMessageSender; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/mailet/mailets/pom.xml ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/pom.xml b/server/mailet/mailets/pom.xml index 5c2dd1e..9e65f80 100644 --- a/server/mailet/mailets/pom.xml +++ b/server/mailet/mailets/pom.xml @@ -67,6 +67,16 @@ </dependency> <dependency> <groupId>${james.groupId}</groupId> + <artifactId>apache-james-spamassassin</artifactId> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>apache-james-spamassassin</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> <artifactId>apache-mailet-api</artifactId> <scope>compile</scope> </dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java index e704497..f9f2634 100644 --- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java @@ -27,11 +27,11 @@ import javax.mail.internet.MimeMessage; import org.apache.james.core.MailAddress; import org.apache.james.metrics.api.MetricFactory; +import org.apache.james.spamassassin.SpamAssassinInvoker; +import org.apache.james.spamassassin.SpamAssassinResult; import org.apache.james.user.api.UsersRepository; import org.apache.james.user.api.UsersRepositoryException; import org.apache.james.util.Port; -import org.apache.james.util.scanner.SpamAssassinInvoker; -import org.apache.james.util.scanner.SpamAssassinResult; import org.apache.mailet.Mail; import org.apache.mailet.PerRecipientHeaders; import org.apache.mailet.base.GenericMailet; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java index 596d2b7..bd516f5 100644 --- a/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java @@ -25,7 +25,7 @@ import java.util.Locale; import javax.mail.MessagingException; import org.apache.james.core.MailAddress; -import org.apache.james.util.scanner.SpamAssassinResult; +import org.apache.james.spamassassin.SpamAssassinResult; import org.apache.mailet.Mail; import org.apache.mailet.base.GenericMatcher; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java index 81f9674..62565ab 100644 --- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java +++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java @@ -27,11 +27,11 @@ import javax.mail.MessagingException; import org.apache.james.core.MailAddress; import org.apache.james.core.builder.MimeMessageBuilder; import org.apache.james.metrics.api.NoopMetricFactory; +import org.apache.james.spamassassin.SpamAssassinResult; +import org.apache.james.spamassassin.mock.MockSpamd; +import org.apache.james.spamassassin.mock.MockSpamdTestRule; import org.apache.james.user.memory.MemoryUsersRepository; import org.apache.james.util.Port; -import org.apache.james.util.scanner.SpamAssassinResult; -import org.apache.james.utils.MockSpamd; -import org.apache.james.utils.MockSpamdTestRule; import org.apache.mailet.Mail; import org.apache.mailet.PerRecipientHeaders; import org.apache.mailet.base.test.FakeMail; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/pom.xml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/pom.xml b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/pom.xml index 986f7db..6309274 100644 --- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/pom.xml +++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/pom.xml @@ -110,6 +110,12 @@ </dependency> <dependency> <groupId>${james.groupId}</groupId> + <artifactId>apache-james-spamassassin</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> <artifactId>james-server-testing</artifactId> <scope>test</scope> </dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java index 3adc452..4c20a0f 100644 --- a/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java +++ b/server/protocols/jmap-integration-testing/cassandra-jmap-integration-testing/src/test/java/org/apache/james/jmap/cassandra/CassandraJmapExtension.java @@ -33,8 +33,8 @@ import org.apache.james.modules.TestESMetricReporterModule; import org.apache.james.modules.TestElasticSearchModule; import org.apache.james.modules.TestJMAPServerModule; import org.apache.james.server.core.configuration.Configuration; +import org.apache.james.spamassassin.SpamAssassinExtension; import org.apache.james.util.Runnables; -import org.apache.james.util.scanner.SpamAssassinExtension; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/jmap-integration-testing/jmap-integration-testing-common/pom.xml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/pom.xml b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/pom.xml index 0adc13f..7f69759 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/pom.xml +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/pom.xml @@ -83,6 +83,12 @@ </dependency> <dependency> <groupId>${james.groupId}</groupId> + <artifactId>apache-james-spamassassin</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> <artifactId>james-server-testing</artifactId> <scope>test</scope> </dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/JamesWithSpamAssassin.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/JamesWithSpamAssassin.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/JamesWithSpamAssassin.java index cedde75..6a10a29 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/JamesWithSpamAssassin.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/JamesWithSpamAssassin.java @@ -19,7 +19,7 @@ package org.apache.james.jmap.methods.integration; import org.apache.james.GuiceJamesServer; -import org.apache.james.util.scanner.SpamAssassinExtension; +import org.apache.james.spamassassin.SpamAssassinExtension; public class JamesWithSpamAssassin { http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SpamAssassinModule.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SpamAssassinModule.java b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SpamAssassinModule.java index ef1ea07..6f8b6d9 100644 --- a/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SpamAssassinModule.java +++ b/server/protocols/jmap-integration-testing/jmap-integration-testing-common/src/test/java/org/apache/james/jmap/methods/integration/SpamAssassinModule.java @@ -25,9 +25,9 @@ import javax.inject.Singleton; import org.apache.commons.configuration.BaseConfiguration; import org.apache.james.mailbox.spamassassin.SpamAssassinConfiguration; import org.apache.james.mailetcontainer.impl.MailetConfigImpl; +import org.apache.james.spamassassin.SpamAssassinExtension; +import org.apache.james.spamassassin.SpamAssassinExtension.SpamAssassin; import org.apache.james.util.Host; -import org.apache.james.util.scanner.SpamAssassinExtension; -import org.apache.james.util.scanner.SpamAssassinExtension.SpamAssassin; import org.apache.james.utils.MailetConfigurationOverride; import com.google.inject.AbstractModule; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/pom.xml ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/pom.xml b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/pom.xml index db2c09c..c873e5e 100644 --- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/pom.xml +++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/pom.xml @@ -74,6 +74,12 @@ </dependency> <dependency> <groupId>${james.groupId}</groupId> + <artifactId>apache-james-spamassassin</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> <artifactId>james-server-memory-guice</artifactId> <type>test-jar</type> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryJmapExtension.java ---------------------------------------------------------------------- diff --git a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryJmapExtension.java b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryJmapExtension.java index 380221f..7ff67b6 100644 --- a/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryJmapExtension.java +++ b/server/protocols/jmap-integration-testing/memory-jmap-integration-testing/src/test/java/org/apache/james/jmap/memory/MemoryJmapExtension.java @@ -32,7 +32,7 @@ import org.apache.james.mailbox.store.search.PDFTextExtractor; import org.apache.james.mailbox.store.search.SimpleMessageSearchIndex; import org.apache.james.modules.TestJMAPServerModule; import org.apache.james.server.core.configuration.Configuration; -import org.apache.james.util.scanner.SpamAssassinExtension; +import org.apache.james.spamassassin.SpamAssassinExtension; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/protocols-smtp/pom.xml ---------------------------------------------------------------------- diff --git a/server/protocols/protocols-smtp/pom.xml b/server/protocols/protocols-smtp/pom.xml index eec9266..1be572d 100644 --- a/server/protocols/protocols-smtp/pom.xml +++ b/server/protocols/protocols-smtp/pom.xml @@ -34,6 +34,16 @@ <dependencies> <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>apache-james-spamassassin</artifactId> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>apache-james-spamassassin</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> <groupId>${javax.activation.groupId}</groupId> <artifactId>${javax.activation.artifactId}</artifactId> <scope>provided</scope> http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java ---------------------------------------------------------------------- diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java index 3a274a8..ef60371 100644 --- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java +++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java @@ -33,8 +33,8 @@ import org.apache.james.protocols.smtp.dsn.DSNStatus; import org.apache.james.protocols.smtp.hook.HookResult; import org.apache.james.protocols.smtp.hook.HookReturnCode; import org.apache.james.smtpserver.JamesMessageHook; -import org.apache.james.util.scanner.SpamAssassinInvoker; -import org.apache.james.util.scanner.SpamAssassinResult; +import org.apache.james.spamassassin.SpamAssassinInvoker; +import org.apache.james.spamassassin.SpamAssassinResult; import org.apache.mailet.Mail; import org.slf4j.Logger; import org.slf4j.LoggerFactory; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java index 97acaea..005bb00 100644 --- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java +++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java @@ -33,9 +33,9 @@ import org.apache.james.protocols.smtp.hook.HookResult; import org.apache.james.protocols.smtp.hook.HookReturnCode; import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession; import org.apache.james.smtpserver.fastfail.SpamAssassinHandler; -import org.apache.james.util.scanner.SpamAssassinResult; -import org.apache.james.utils.MockSpamd; -import org.apache.james.utils.MockSpamdTestRule; +import org.apache.james.spamassassin.SpamAssassinResult; +import org.apache.james.spamassassin.mock.MockSpamd; +import org.apache.james.spamassassin.mock.MockSpamdTestRule; import org.apache.mailet.Mail; import org.apache.mailet.base.test.FakeMail; import org.junit.Rule; http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/testing/src/main/java/org/apache/james/utils/MockSpamd.java ---------------------------------------------------------------------- diff --git a/server/testing/src/main/java/org/apache/james/utils/MockSpamd.java b/server/testing/src/main/java/org/apache/james/utils/MockSpamd.java deleted file mode 100644 index 45121c7..0000000 --- a/server/testing/src/main/java/org/apache/james/utils/MockSpamd.java +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ -package org.apache.james.utils; - -import static org.apache.commons.io.output.NullOutputStream.NULL_OUTPUT_STREAM; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.ServerSocket; -import java.net.Socket; -import java.nio.charset.StandardCharsets; - -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Preconditions; - -/** - * This class can be used to run a mocked SPAMD daemon - */ -public class MockSpamd implements Runnable { - private static final Logger LOGGER = LoggerFactory.getLogger(MockSpamd.class); - - /** - * Mailcontent which is 100% spam - */ - public static final String GTUBE = "-SPAM-"; - public static final String NOT_SPAM = "Spam: False ; 3 / 5"; - public static final String SPAM = "Spam: True ; 1000 / 5"; - - private ServerSocket socket; - private boolean isBinded; - - public MockSpamd() { - isBinded = false; - } - - public int getPort() { - Preconditions.checkState(isBinded, "SpamD mock server is not binded"); - return socket.getLocalPort(); - } - - public void bind() throws IOException { - socket = new ServerSocket(0); - isBinded = true; - } - - @Override - public void run() { - try (ServerSocket serverSocket = socket; - Socket spamd = serverSocket.accept(); - BufferedReader in = new BufferedReader(new InputStreamReader(spamd.getInputStream())); - OutputStream out = spamd.getOutputStream()) { - - handleRequest(in, out); - } catch (IOException e) { - LOGGER.error("Exception while handling answer", e); - } - } - - private void handleRequest(BufferedReader in, OutputStream out) throws IOException { - if (isSpam(in)) { - out.write(SPAM.getBytes()); - } else { - out.write(NOT_SPAM.getBytes()); - } - out.flush(); - } - - private boolean isSpam(BufferedReader in) throws IOException { - try { - return in.lines() - .anyMatch(line -> line.contains(GTUBE)); - } finally { - consume(in); - } - } - - private void consume(BufferedReader in) throws IOException { - IOUtils.copy(in, NULL_OUTPUT_STREAM, StandardCharsets.UTF_8); - } -} http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/server/testing/src/main/java/org/apache/james/utils/MockSpamdTestRule.java ---------------------------------------------------------------------- diff --git a/server/testing/src/main/java/org/apache/james/utils/MockSpamdTestRule.java b/server/testing/src/main/java/org/apache/james/utils/MockSpamdTestRule.java deleted file mode 100644 index ea746df..0000000 --- a/server/testing/src/main/java/org/apache/james/utils/MockSpamdTestRule.java +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************** - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ****************************************************************/ - -package org.apache.james.utils; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.junit.rules.ExternalResource; - -public class MockSpamdTestRule extends ExternalResource { - - private ExecutorService executor = Executors.newSingleThreadExecutor(); - private MockSpamd spamd = new MockSpamd(); - - @Override - protected void before() throws Throwable { - spamd.bind(); - executor.execute(spamd); - } - - public int getPort() { - return spamd.getPort(); - } - - @Override - protected void after() { - executor.shutdownNow(); - } -} http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/third-party/pom.xml ---------------------------------------------------------------------- diff --git a/third-party/pom.xml b/third-party/pom.xml new file mode 100644 index 0000000..0ee2019 --- /dev/null +++ b/third-party/pom.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.james</groupId> + <artifactId>james-project</artifactId> + <version>3.2.0-SNAPSHOT</version> + </parent> + + <artifactId>third-party</artifactId> + <packaging>pom</packaging> + + <name>Apache JAMES third party</name> + <description>Common utilities for integrating with third party software</description> + <inceptionYear>2018</inceptionYear> + + <modules> + <module>spamassassin</module> + </modules> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/third-party/spamassassin/pom.xml ---------------------------------------------------------------------- diff --git a/third-party/spamassassin/pom.xml b/third-party/spamassassin/pom.xml new file mode 100644 index 0000000..4b1da22 --- /dev/null +++ b/third-party/spamassassin/pom.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.james</groupId> + <artifactId>third-party</artifactId> + <version>3.2.0-SNAPSHOT</version> + </parent> + + <artifactId>apache-james-spamassassin</artifactId> + + <dependencies> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>javax-mail-extension</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> + <groupId>${james.groupId}</groupId> + <artifactId>metrics-api</artifactId> + </dependency> + <dependency> + <groupId>com.github.fge</groupId> + <artifactId>throwing-lambdas</artifactId> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </dependency> + <dependency> + <groupId>com.sun.mail</groupId> + <artifactId>javax.mail</artifactId> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-launcher</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.testcontainers</groupId> + <artifactId>testcontainers</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinInvoker.java ---------------------------------------------------------------------- diff --git a/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinInvoker.java b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinInvoker.java new file mode 100644 index 0000000..2a9fd8a --- /dev/null +++ b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinInvoker.java @@ -0,0 +1,251 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.spamassassin; + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; + +import org.apache.commons.io.IOUtils; +import org.apache.james.metrics.api.MetricFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.github.fge.lambdas.Throwing; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; + +/** + * Sends the message through daemonized SpamAssassin (spamd), visit <a + * href="SpamAssassin.org">SpamAssassin.org</a> for info on configuration. + */ +public class SpamAssassinInvoker { + private static final Logger LOGGER = LoggerFactory.getLogger(SpamAssassinInvoker.class); + + enum MessageClass { + HAM("ham"), + SPAM("spam"); + + private final String value; + + MessageClass(String value) { + this.value = value; + } + } + + private static final int SPAM_INDEX = 1; + private static final int HITS_INDEX = 3; + private static final int REQUIRED_HITS_INDEX = 5; + private static final String CRLF = "\r\n"; + + private final MetricFactory metricFactory; + private final String spamdHost; + private final int spamdPort; + + /** + * Init the spamassassin invoker + * + * @param spamdHost + * The host on which spamd runs + * @param spamdPort + */ + public SpamAssassinInvoker(MetricFactory metricFactory, String spamdHost, int spamdPort) { + this.metricFactory = metricFactory; + this.spamdHost = spamdHost; + this.spamdPort = spamdPort; + } + + /** + * Scan a MimeMessage for spam by passing it to spamd. + * + * @param message + * The MimeMessage to scan + * @return true if spam otherwise false + * @throws MessagingException + * if an error on scanning is detected + */ + public SpamAssassinResult scanMail(MimeMessage message, String user) throws MessagingException { + return metricFactory.withMetric( + "spamAssassin-check", + Throwing.supplier( + () -> scanMailWithAdditionalHeaders(message, + "User: " + user)) + .sneakyThrow()); + } + + public SpamAssassinResult scanMail(MimeMessage message) throws MessagingException { + return metricFactory.withMetric( + "spamAssassin-check", + Throwing.supplier( + () -> scanMailWithoutAdditionalHeaders(message)) + .sneakyThrow()); + } + + public SpamAssassinResult scanMailWithAdditionalHeaders(MimeMessage message, String... additionalHeaders) throws MessagingException { + try (Socket socket = new Socket(spamdHost, spamdPort); + OutputStream out = socket.getOutputStream(); + BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out); + PrintWriter writer = new PrintWriter(bufferedOutputStream); + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { + + writer.write("CHECK SPAMC/1.2"); + writer.write(CRLF); + + Arrays.stream(additionalHeaders) + .forEach(header -> { + writer.write(header); + writer.write(CRLF); + }); + + writer.write(CRLF); + writer.flush(); + + // pass the message to spamd + message.writeTo(out); + out.flush(); + socket.shutdownOutput(); + + return in.lines() + .filter(this::isSpam) + .map(this::processSpam) + .findFirst() + .orElse(SpamAssassinResult.empty()); + } catch (UnknownHostException e) { + throw new MessagingException("Error communicating with spamd. Unknown host: " + spamdHost); + } catch (IOException | MessagingException e) { + throw new MessagingException("Error communicating with spamd on " + spamdHost + ":" + spamdPort, e); + } + } + + public SpamAssassinResult scanMailWithoutAdditionalHeaders(MimeMessage message) throws MessagingException { + return scanMailWithAdditionalHeaders(message); + } + + private SpamAssassinResult processSpam(String line) { + List<String> elements = Lists.newArrayList(Splitter.on(' ').split(line)); + + return builderFrom(elements) + .hits(elements.get(HITS_INDEX)) + .requiredHits(elements.get(REQUIRED_HITS_INDEX)) + .build(); + } + + private SpamAssassinResult.Builder builderFrom(List<String> elements) { + if (spam(elements.get(SPAM_INDEX))) { + return SpamAssassinResult.asSpam(); + } else { + return SpamAssassinResult.asHam(); + } + } + + private boolean spam(String string) { + try { + return Boolean.valueOf(string); + } catch (Exception e) { + LOGGER.warn("Fail parsing spamassassin answer: " + string); + return false; + } + } + + private boolean isSpam(String line) { + return line.startsWith("Spam:"); + } + + /** + * Tell spamd that the given MimeMessage is a spam. + * + * @param message + * The MimeMessage to tell + * @throws MessagingException + * if an error occured during learning. + */ + public boolean learnAsSpam(InputStream message, String user) throws MessagingException { + return metricFactory.withMetric( + "spamAssassin-spam-report", + Throwing.supplier( + () -> reportMessageAs(message, user, MessageClass.SPAM)) + .sneakyThrow()); + } + + /** + * Tell spamd that the given MimeMessage is a ham. + * + * @param message + * The MimeMessage to tell + * @throws MessagingException + * if an error occured during learning. + */ + public boolean learnAsHam(InputStream message, String user) throws MessagingException { + return metricFactory.withMetric( + "spamAssassin-ham-report", + Throwing.supplier( + () -> reportMessageAs(message, user, MessageClass.HAM)) + .sneakyThrow()); + } + + private boolean reportMessageAs(InputStream message, String user, MessageClass messageClass) throws MessagingException { + try (Socket socket = new Socket(spamdHost, spamdPort); + OutputStream out = socket.getOutputStream(); + BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out); + PrintWriter writer = new PrintWriter(bufferedOutputStream); + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { + + byte[] byteArray = IOUtils.toByteArray(message); + writer.write("TELL SPAMC/1.2"); + writer.write(CRLF); + writer.write("Content-length: " + byteArray.length); + writer.write(CRLF); + writer.write("Message-class: " + messageClass.value); + writer.write(CRLF); + writer.write("Set: local, remote"); + writer.write(CRLF); + writer.write("User: " + user); + writer.write(CRLF); + writer.write(CRLF); + writer.flush(); + + out.write(byteArray); + out.flush(); + socket.shutdownOutput(); + + return in.lines() + .anyMatch(this::hasBeenSet); + } catch (UnknownHostException e) { + throw new MessagingException("Error communicating with spamd. Unknown host: " + spamdHost); + } catch (IOException e) { + throw new MessagingException("Error communicating with spamd on " + spamdHost + ":" + spamdPort, e); + } + } + + private boolean hasBeenSet(String line) { + return line.startsWith("DidSet: "); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinResult.java ---------------------------------------------------------------------- diff --git a/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinResult.java b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinResult.java new file mode 100644 index 0000000..96f98ea --- /dev/null +++ b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinResult.java @@ -0,0 +1,109 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ +package org.apache.james.spamassassin; + +import java.util.Map; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; + +public class SpamAssassinResult { + /** The mail attribute under which the status get stored */ + public static final String STATUS_MAIL_ATTRIBUTE_NAME = "org.apache.james.spamassassin.status"; + + /** The mail attribute under which the flag get stored */ + public static final String FLAG_MAIL_ATTRIBUTE_NAME = "org.apache.james.spamassassin.flag"; + + public static final String NO_RESULT = "?"; + + public static SpamAssassinResult empty() { + return asHam() + .hits(NO_RESULT) + .requiredHits(NO_RESULT) + .build(); + } + + public static Builder asSpam() { + return new Builder(true); + } + + public static Builder asHam() { + return new Builder(false); + } + + public static class Builder { + + private String hits; + private String requiredHits; + private final boolean isSpam; + + private Builder(boolean isSpam) { + this.isSpam = isSpam; + } + + public Builder hits(String hits) { + this.hits = hits; + return this; + } + + public Builder requiredHits(String requiredHits) { + this.requiredHits = requiredHits; + return this; + } + + public SpamAssassinResult build() { + Preconditions.checkNotNull(hits); + Preconditions.checkNotNull(requiredHits); + + ImmutableMap.Builder<String, String> headersAsAttribute = ImmutableMap.builder(); + if (isSpam) { + headersAsAttribute.put(FLAG_MAIL_ATTRIBUTE_NAME, "YES"); + headersAsAttribute.put(STATUS_MAIL_ATTRIBUTE_NAME, "Yes, hits=" + hits + " required=" + requiredHits); + } else { + headersAsAttribute.put(FLAG_MAIL_ATTRIBUTE_NAME, "NO"); + headersAsAttribute.put(STATUS_MAIL_ATTRIBUTE_NAME, "No, hits=" + hits + " required=" + requiredHits); + } + + return new SpamAssassinResult(hits, requiredHits, headersAsAttribute.build()); + } + } + + private final String hits; + private final String requiredHits; + private final Map<String, String> headersAsAttribute; + + private SpamAssassinResult(String hits, String requiredHits, Map<String, String> headersAsAttribute) { + this.hits = hits; + this.requiredHits = requiredHits; + this.headersAsAttribute = headersAsAttribute; + } + + public String getHits() { + return hits; + } + + public String getRequiredHits() { + return requiredHits; + } + + public Map<String, String> getHeadersAsAttribute() { + return headersAsAttribute; + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinExtension.java ---------------------------------------------------------------------- diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinExtension.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinExtension.java new file mode 100644 index 0000000..fd4980c --- /dev/null +++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinExtension.java @@ -0,0 +1,148 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.spamassassin; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Locale; +import java.util.stream.Stream; + +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; + +import com.github.fge.lambdas.Throwing; + +public class SpamAssassinExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver { + + private final GenericContainer<?> spamAssassinContainer; + private SpamAssassin spamAssassin; + + public SpamAssassinExtension() { + spamAssassinContainer = new GenericContainer<>( + new ImageFromDockerfile() + .withFileFromClasspath("Dockerfile", "docker/spamassassin/Dockerfile") + .withFileFromClasspath("local.cf", "docker/spamassassin/local.cf") + .withFileFromClasspath("run.sh", "docker/spamassassin/run.sh") + .withFileFromClasspath("spamd.sh", "docker/spamassassin/spamd.sh") + .withFileFromClasspath("rule-update.sh", "docker/spamassassin/rule-update.sh") + .withFileFromClasspath("bayes_pg.sql", "docker/spamassassin/bayes_pg.sql")); + spamAssassinContainer.waitingFor(new SpamAssassinWaitStrategy(spamAssassinContainer)); + } + + @Override + public void beforeEach(ExtensionContext context) { + spamAssassinContainer.start(); + spamAssassin = new SpamAssassin(spamAssassinContainer); + } + + @Override + public void afterEach(ExtensionContext context) { + spamAssassinContainer.close(); + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + return (parameterContext.getParameter().getType() == SpamAssassin.class); + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + return spamAssassin; + } + + public SpamAssassin getSpamAssassin() { + return spamAssassin; + } + + public static class SpamAssassin { + + private static final int SPAMASSASSIN_PORT = 783; + + private final String ip; + private final int bindingPort; + private final GenericContainer<?> spamAssassinContainer; + + private SpamAssassin(GenericContainer<?> spamAssassinContainer) { + this.spamAssassinContainer = spamAssassinContainer; + this.ip = spamAssassinContainer.getContainerIpAddress(); + this.bindingPort = spamAssassinContainer.getMappedPort(SPAMASSASSIN_PORT); + } + + public String getIp() { + return ip; + } + + public int getBindingPort() { + return bindingPort; + } + + public void train(String user) throws IOException, URISyntaxException { + train(user, Paths.get(ClassLoader.getSystemResource("spamassassin_db/spam").toURI()), TrainingKind.SPAM); + train(user, Paths.get(ClassLoader.getSystemResource("spamassassin_db/ham").toURI()), TrainingKind.HAM); + } + + private void train(String user, Path folder, TrainingKind trainingKind) throws IOException { + spamAssassinContainer.getDockerClient().copyArchiveToContainerCmd(spamAssassinContainer.getContainerId()) + .withHostResource(folder.toAbsolutePath().toString()) + .withRemotePath("/root") + .exec(); + try (Stream<Path> paths = Files.walk(folder)) { + paths + .filter(Files::isRegularFile) + .map(Path::toFile) + .forEach(Throwing.consumer(file -> spamAssassinContainer.execInContainer("sa-learn", + trainingKind.saLearnExtensionName(), "-u", user, + "/root/" + trainingKind.name().toLowerCase(Locale.US) + "/" + file.getName()))); + } + } + + private enum TrainingKind { + SPAM("--spam"), HAM("--ham"); + + private String saLearnExtensionName; + + TrainingKind(String saLearnExtensionName) { + this.saLearnExtensionName = saLearnExtensionName; + } + + public String saLearnExtensionName() { + return saLearnExtensionName; + } + } + + public void sync(String user) throws UnsupportedOperationException, IOException, InterruptedException { + spamAssassinContainer.execInContainer("sa-learn", "--sync", "-u", user); + } + + public void dump(String user) throws UnsupportedOperationException, IOException, InterruptedException { + spamAssassinContainer.execInContainer("sa-learn", "--dump", "magic", "-u", user); + } + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinInvokerTest.java ---------------------------------------------------------------------- diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinInvokerTest.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinInvokerTest.java new file mode 100644 index 0000000..473c6bf --- /dev/null +++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinInvokerTest.java @@ -0,0 +1,147 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ +package org.apache.james.spamassassin; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; + +import javax.mail.internet.MimeMessage; + +import org.apache.james.metrics.api.NoopMetricFactory; +import org.apache.james.spamassassin.SpamAssassinExtension.SpamAssassin; +import org.apache.james.util.MimeMessageUtil; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(SpamAssassinExtension.class) +public class SpamAssassinInvokerTest { + + public static final String USER = "any@james"; + private SpamAssassin spamAssassin; + private SpamAssassinInvoker testee; + + @BeforeEach + public void setup(SpamAssassin spamAssassin) throws Exception { + this.spamAssassin = spamAssassin; + testee = new SpamAssassinInvoker(new NoopMetricFactory(), spamAssassin.getIp(), spamAssassin.getBindingPort()); + } + + @Test + public void scanMailShouldModifyHitsField() throws Exception { + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("eml/spam.eml")); + SpamAssassinResult result = testee.scanMail(mimeMessage, USER); + + assertThat(result.getHits()).isNotEqualTo(SpamAssassinResult.NO_RESULT); + } + + @Test + public void scanMailShouldModifyRequiredHitsField() throws Exception { + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("eml/spam.eml")); + SpamAssassinResult result = testee.scanMail(mimeMessage, USER); + + assertThat(result.getRequiredHits()).isEqualTo("5.0"); + } + + @Test + public void scanMailShouldModifyHeadersField() throws Exception { + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("eml/spam.eml")); + SpamAssassinResult result = testee.scanMail(mimeMessage, USER); + + assertThat(result.getHeadersAsAttribute()).isNotEmpty(); + } + + @Test + public void scanMailShouldMarkAsSpamWhenKnownAsSpam() throws Exception { + spamAssassin.train("user"); + + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("spamassassin_db/spam/spam1")); + + SpamAssassinResult result = testee.scanMail(mimeMessage, USER); + + assertThat(result.getHeadersAsAttribute().get(SpamAssassinResult.FLAG_MAIL_ATTRIBUTE_NAME)).isEqualTo("YES"); + } + + @Test + public void learnAsSpamShouldReturnTrueWhenLearningWorks() throws Exception { + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("spamassassin_db/spam/spam2")); + + boolean result = testee.learnAsSpam(mimeMessage.getInputStream(), USER); + + assertThat(result).isTrue(); + } + + @Test + public void scanMailShouldMarkAsSpamWhenMessageAlreadyLearnedAsSpam() throws Exception { + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("spamassassin_db/spam/spam1")); + + byte[] messageAsBytes = MimeMessageUtil.asString(mimeMessage).getBytes(StandardCharsets.UTF_8); + + testee.learnAsSpam(new ByteArrayInputStream(messageAsBytes), USER); + + SpamAssassinResult result = testee.scanMail(mimeMessage, USER); + + assertThat(result.getHeadersAsAttribute().get(SpamAssassinResult.FLAG_MAIL_ATTRIBUTE_NAME)).isEqualTo("YES"); + } + + @Test + public void learnAsHamShouldReturnTrueWhenLearningWorks() throws Exception { + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("spamassassin_db/ham/ham2")); + + boolean result = testee.learnAsHam(mimeMessage.getInputStream(), USER); + + assertThat(result).isTrue(); + } + + @Test + public void scanMailShouldMarkAsHamWhenMessageAlreadyLearnedAsHam() throws Exception { + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("spamassassin_db/ham/ham1")); + + testee.learnAsHam(mimeMessage.getInputStream(), USER); + + SpamAssassinResult result = testee.scanMail(mimeMessage, USER); + + assertThat(result.getHeadersAsAttribute().get(SpamAssassinResult.FLAG_MAIL_ATTRIBUTE_NAME)).isEqualTo("NO"); + } + + @Test + public void learnAsHamShouldAllowToForgetSpam() throws Exception { + MimeMessage mimeMessage = MimeMessageUtil.mimeMessageFromStream( + ClassLoader.getSystemResourceAsStream("eml/spam.eml")); + + byte[] messageAsBytes = MimeMessageUtil.asString(mimeMessage).getBytes(StandardCharsets.UTF_8); + + testee.learnAsSpam(new ByteArrayInputStream(messageAsBytes), USER); + testee.learnAsHam(new ByteArrayInputStream(messageAsBytes), USER); + + SpamAssassinResult result = testee.scanMail(mimeMessage, USER); + + assertThat(result.getHeadersAsAttribute().get(SpamAssassinResult.FLAG_MAIL_ATTRIBUTE_NAME)).isEqualTo("NO"); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinResultTest.java ---------------------------------------------------------------------- diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinResultTest.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinResultTest.java new file mode 100644 index 0000000..fb75604 --- /dev/null +++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinResultTest.java @@ -0,0 +1,96 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ +package org.apache.james.spamassassin; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.assertj.core.api.JUnitSoftAssertions; +import org.junit.Rule; +import org.junit.Test; + +import com.google.common.collect.ImmutableMap; + +public class SpamAssassinResultTest { + + @Rule + public JUnitSoftAssertions softly = new JUnitSoftAssertions(); + + @Test + public void buildShouldThrowWhenHitsIsNotGiven() { + assertThatThrownBy(() -> SpamAssassinResult.asSpam() + .requiredHits("4.0") + .build()) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void buildShouldThrowWhenRequiredHitsIsNotGiven() { + assertThatThrownBy(() -> SpamAssassinResult.asSpam() + .hits("4.0") + .build()) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void buildShouldWork() { + String hits = "1.1"; + String requiredHits = "5.0"; + + SpamAssassinResult spamAssassinResult = SpamAssassinResult.asSpam() + .hits(hits) + .requiredHits(requiredHits) + .build(); + + softly.assertThat(spamAssassinResult.getHits()).isEqualTo(hits); + softly.assertThat(spamAssassinResult.getRequiredHits()).isEqualTo(requiredHits); + softly.assertThat(spamAssassinResult.getHeadersAsAttribute()) + .containsAllEntriesOf(ImmutableMap.of( + SpamAssassinResult.FLAG_MAIL_ATTRIBUTE_NAME, "YES", + SpamAssassinResult.STATUS_MAIL_ATTRIBUTE_NAME, "Yes, hits=1.1 required=5.0")); + } + + @Test + public void headersAsAttributeShouldContainSpamHeaderWithYESValueWhenBuiltAsSpam() { + String hits = "1.1"; + String requiredHits = "5.0"; + + SpamAssassinResult spamAssassinResult = SpamAssassinResult.asSpam() + .hits(hits) + .requiredHits(requiredHits) + .build(); + + assertThat(spamAssassinResult.getHeadersAsAttribute()) + .containsEntry(SpamAssassinResult.FLAG_MAIL_ATTRIBUTE_NAME, "YES"); + } + + @Test + public void headersAsAttributeShouldContainSpamHeaderWithNOValueWhenBuiltAsHam() { + String hits = "1.1"; + String requiredHits = "5.0"; + + SpamAssassinResult spamAssassinResult = SpamAssassinResult.asHam() + .hits(hits) + .requiredHits(requiredHits) + .build(); + + assertThat(spamAssassinResult.getHeadersAsAttribute()) + .containsEntry(SpamAssassinResult.FLAG_MAIL_ATTRIBUTE_NAME, "NO"); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/1fd63a7f/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinWaitStrategy.java ---------------------------------------------------------------------- diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinWaitStrategy.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinWaitStrategy.java new file mode 100644 index 0000000..c9f1c7a --- /dev/null +++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinWaitStrategy.java @@ -0,0 +1,67 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.spamassassin; + +import java.io.IOException; +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +import org.rnorth.ducttape.unreliables.Unreliables; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.containers.wait.strategy.WaitStrategyTarget; + +import com.google.common.primitives.Ints; + +public class SpamAssassinWaitStrategy implements WaitStrategy { + + private static final Duration DEFAULT_TIMEOUT = Duration.ofMinutes(1); + private final GenericContainer<?> spamAssassinContainer; + private Duration timeout = DEFAULT_TIMEOUT; + + public SpamAssassinWaitStrategy(GenericContainer<?> spamAssassinContainer) { + this(spamAssassinContainer, DEFAULT_TIMEOUT); + } + + public SpamAssassinWaitStrategy(GenericContainer<?> spamAssassinContainer, Duration timeout) { + this.spamAssassinContainer = spamAssassinContainer; + this.timeout = timeout; + } + + @Override + public void waitUntilReady(WaitStrategyTarget waitStrategyTarget) { + Unreliables.retryUntilTrue(Ints.checkedCast(timeout.getSeconds()), TimeUnit.SECONDS, () -> { + try { + return spamAssassinContainer + .execInContainer("spamassassin", "-V") + .getStdout() + .contains("SpamAssassin version 3.4.1"); + } catch (IOException | InterruptedException e) { + return false; + } + } + ); + } + + @Override + public WaitStrategy withStartupTimeout(Duration startupTimeout) { + return new SpamAssassinWaitStrategy(spamAssassinContainer, startupTimeout); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org