Compare commits
2 Commits
b71d9e2ded
...
7e646d2ae9
Author | SHA1 | Date | |
---|---|---|---|
7e646d2ae9 | |||
f06d2e7219 |
@ -4,13 +4,16 @@ WORKDIR /usr/src/app
|
|||||||
|
|
||||||
COPY requirements.txt ./
|
COPY requirements.txt ./
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
RUN apk add python3-dev build-base linux-headers pcre-dev
|
RUN apk add python3-dev build-base linux-headers pcre-dev spamassassin
|
||||||
RUN pip install uwsgi
|
RUN pip install uwsgi
|
||||||
|
#spamassassin_client
|
||||||
|
|
||||||
ENV UID=0
|
ENV UID=0
|
||||||
ENV MOUNT=/
|
ENV MOUNT=/
|
||||||
|
|
||||||
COPY ./main.py ./
|
# Since the package maintainer doesnt merge PR
|
||||||
|
# https://github.com/petermat/spamassassin_client/pull/2
|
||||||
|
COPY ./main.py ./spamassassin/spamassasin_client.py ./
|
||||||
|
|
||||||
# I juste wanted to change the socket owner but it turned out I needed to change thu uwsgi user
|
# I juste wanted to change the socket owner but it turned out I needed to change thu uwsgi user
|
||||||
#CMD uwsgi --exec-asap 'chown $UID:$UID /tmp/uwsgi/ ; mkdir -p $BASE_PATH && chown $UID:$UID $BASE_PATH' -s /tmp/uwsgi/uwsgi.sock --uid $UID --manage-script-name --mount /=server:app
|
#CMD uwsgi --exec-asap 'chown $UID:$UID /tmp/uwsgi/ ; mkdir -p $BASE_PATH && chown $UID:$UID $BASE_PATH' -s /tmp/uwsgi/uwsgi.sock --uid $UID --manage-script-name --mount /=server:app
|
||||||
|
@ -14,6 +14,7 @@ import random, string # for tokens
|
|||||||
import html # for sanitization
|
import html # for sanitization
|
||||||
from bson.json_util import dumps
|
from bson.json_util import dumps
|
||||||
import datetime # For email date
|
import datetime # For email date
|
||||||
|
from spamassasin_client import SpamAssassin
|
||||||
|
|
||||||
|
|
||||||
##################################################### Bottle stuff ############################################
|
##################################################### Bottle stuff ############################################
|
||||||
@ -136,7 +137,10 @@ def submission ():
|
|||||||
content = re.sub(form_regex, r'{\1}', form['content']).format(**content_fields)
|
content = re.sub(form_regex, r'{\1}', form['content']).format(**content_fields)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if not send_mail(from_address, form['mail'], subject, content):
|
msg = build_mail(from_address, form['mail'], subject, content)
|
||||||
|
if is_spam(msg):
|
||||||
|
return resp(400, 'Votre message semble être du spam !')
|
||||||
|
if not send_mail(form['mail'], msg):
|
||||||
return resp(500, 'Le mail n’a pas pu être envoyé.')
|
return resp(500, 'Le mail n’a pas pu être envoyé.')
|
||||||
except smtplib.SMTPDataError as e:
|
except smtplib.SMTPDataError as e:
|
||||||
response.status = 500
|
response.status = 500
|
||||||
@ -178,8 +182,7 @@ def fill_fields(request, fields):
|
|||||||
raise MissingParameterException("Le champs {} est obligatoire".format(field))
|
raise MissingParameterException("Le champs {} est obligatoire".format(field))
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
def send_mail (from_address, to, subject, content):
|
def build_mail(from_address, to, subject, content):
|
||||||
"""Actually connect to smtp server, build a message object and send it as a mail"""
|
|
||||||
msg = EmailMessage()
|
msg = EmailMessage()
|
||||||
msg['From'] = smtp_server_sender
|
msg['From'] = smtp_server_sender
|
||||||
msg.add_header('reply-to', from_address)
|
msg.add_header('reply-to', from_address)
|
||||||
@ -189,8 +192,16 @@ def send_mail (from_address, to, subject, content):
|
|||||||
msg.set_content(MIMEText(content, 'plain', "utf-8"))
|
msg.set_content(MIMEText(content, 'plain', "utf-8"))
|
||||||
#or
|
#or
|
||||||
#msg.set_content(content)
|
#msg.set_content(content)
|
||||||
|
return msg
|
||||||
|
|
||||||
|
def is_spam(msg):
|
||||||
|
assassin = SpamAssassin(msg.as_string().encode(), 'spamassassin')
|
||||||
|
return assassin.is_spam()
|
||||||
|
|
||||||
|
def send_mail (to, msg):
|
||||||
|
"""Actually connect to smtp server and send the mail"""
|
||||||
if do_not_send:
|
if do_not_send:
|
||||||
print('------------------------------------ Following message wont be sent ------------------------------------')
|
print('-------------------------- Following message sent. But only to stdout ----------------------------------')
|
||||||
print(msg.as_string())
|
print(msg.as_string())
|
||||||
print('--------------------------------------------------------------------------------------------------------')
|
print('--------------------------------------------------------------------------------------------------------')
|
||||||
return True
|
return True
|
||||||
|
2
server/spamassassin/readme
Normal file
2
server/spamassassin/readme
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Since the package maintainer doesnt merge PR
|
||||||
|
https://github.com/petermat/spamassassin_client/pull/2
|
115
server/spamassassin/spamassasin_client.py
Normal file
115
server/spamassassin/spamassasin_client.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import socket, select, re, logging
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
divider_pattern = re.compile(br'^(.*?)\r?\n(.*?)\r?\n\r?\n', re.DOTALL)
|
||||||
|
first_line_pattern = re.compile(br'^SPAMD/[^ ]+ 0 EX_OK$')
|
||||||
|
|
||||||
|
|
||||||
|
class SpamAssassin(object):
|
||||||
|
def __init__(self, message, host='127.0.0.1', port=783, timeout=20):
|
||||||
|
self.score = None
|
||||||
|
self.symbols = None
|
||||||
|
|
||||||
|
# Connecting
|
||||||
|
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
client.settimeout(timeout)
|
||||||
|
client.connect((host, port))
|
||||||
|
|
||||||
|
# Sending
|
||||||
|
client.sendall(self._build_message(message))
|
||||||
|
client.shutdown(socket.SHUT_WR)
|
||||||
|
|
||||||
|
# Reading
|
||||||
|
resfp = BytesIO()
|
||||||
|
while True:
|
||||||
|
ready = select.select([client], [], [], timeout)
|
||||||
|
if ready[0] is None:
|
||||||
|
# Kill with Timeout!
|
||||||
|
logging.info('[SpamAssassin] - Timeout ({0}s)!'.format(str(timeout)))
|
||||||
|
break
|
||||||
|
|
||||||
|
data = client.recv(4096)
|
||||||
|
if data == b'':
|
||||||
|
break
|
||||||
|
|
||||||
|
resfp.write(data)
|
||||||
|
|
||||||
|
# Closing
|
||||||
|
client.close()
|
||||||
|
client = None
|
||||||
|
|
||||||
|
self._parse_response(resfp.getvalue())
|
||||||
|
|
||||||
|
def _build_message(self, message):
|
||||||
|
reqfp = BytesIO()
|
||||||
|
data_len = str(len(message)).encode()
|
||||||
|
reqfp.write(b'REPORT SPAMC/1.2\r\n')
|
||||||
|
reqfp.write(b'Content-Length: ' + data_len + b'\r\n')
|
||||||
|
reqfp.write(b'User: cx42\r\n\r\n')
|
||||||
|
reqfp.write(message)
|
||||||
|
return reqfp.getvalue()
|
||||||
|
|
||||||
|
def _parse_response(self, response):
|
||||||
|
if response == b'':
|
||||||
|
logging.info("[SPAM ASSASSIN] Empty response")
|
||||||
|
return None
|
||||||
|
|
||||||
|
match = divider_pattern.match(response)
|
||||||
|
if not match:
|
||||||
|
logging.error("[SPAM ASSASSIN] Response error:")
|
||||||
|
logging.error(response)
|
||||||
|
return None
|
||||||
|
|
||||||
|
first_line = match.group(1)
|
||||||
|
headers = match.group(2)
|
||||||
|
body = response[match.end(0):]
|
||||||
|
|
||||||
|
# Checking response is good
|
||||||
|
match = first_line_pattern.match(first_line)
|
||||||
|
if not match:
|
||||||
|
logging.error("[SPAM ASSASSIN] invalid response:")
|
||||||
|
logging.error(first_line)
|
||||||
|
return None
|
||||||
|
|
||||||
|
report_list = [s.strip() for s in body.decode('utf-8').strip().split('\n')]
|
||||||
|
linebreak_num = report_list.index([s for s in report_list if "---" in s][0])
|
||||||
|
tablelists = [s for s in report_list[linebreak_num + 1:]]
|
||||||
|
|
||||||
|
self.report_fulltext = '\n'.join(report_list)
|
||||||
|
|
||||||
|
|
||||||
|
# join line when current one is only wrap of previous
|
||||||
|
tablelists_temp = []
|
||||||
|
if tablelists:
|
||||||
|
for counter, tablelist in enumerate(tablelists):
|
||||||
|
if len(tablelist)>1:
|
||||||
|
if (tablelist[0].isnumeric() or tablelist[0] == '-') and (tablelist[1].isnumeric() or tablelist[1] == '.'):
|
||||||
|
tablelists_temp.append(tablelist)
|
||||||
|
else:
|
||||||
|
if tablelists_temp:
|
||||||
|
tablelists_temp[-1] += " " + tablelist
|
||||||
|
tablelists = tablelists_temp
|
||||||
|
|
||||||
|
# create final json
|
||||||
|
self.report_json = dict()
|
||||||
|
for tablelist in tablelists:
|
||||||
|
wordlist = re.split('\s+', tablelist)
|
||||||
|
self.report_json[wordlist[1]] = {'partscore': float(wordlist[0]), 'description': ' '.join(wordlist[1:])}
|
||||||
|
|
||||||
|
headers = headers.decode('utf-8').replace(' ', '').replace(':', ';').replace('/', ';').split(';')
|
||||||
|
self.score = float(headers[2])
|
||||||
|
|
||||||
|
def get_report_json(self):
|
||||||
|
return self.report_json
|
||||||
|
|
||||||
|
def get_score(self):
|
||||||
|
return self.score
|
||||||
|
|
||||||
|
def is_spam(self, level=5):
|
||||||
|
return self.score is None or self.score > level
|
||||||
|
|
||||||
|
def get_fulltext(self):
|
||||||
|
return self.report_fulltext
|
||||||
|
|
||||||
|
|
||||||
|
|
383
server/spamassassin/spamassassin_client
Normal file
383
server/spamassassin/spamassassin_client
Normal file
@ -0,0 +1,383 @@
|
|||||||
|
%!PS-Adobe-3.0
|
||||||
|
%%Creator: (ImageMagick)
|
||||||
|
%%Title: (spamassassin_client)
|
||||||
|
%%CreationDate: (2021-05-17T23:08:26+00:00)
|
||||||
|
%%BoundingBox: 428 345 508 391
|
||||||
|
%%HiResBoundingBox: 428 345 508 391
|
||||||
|
%%DocumentData: Clean7Bit
|
||||||
|
%%LanguageLevel: 1
|
||||||
|
%%Orientation: Portrait
|
||||||
|
%%PageOrder: Ascend
|
||||||
|
%%Pages: 1
|
||||||
|
%%EndComments
|
||||||
|
|
||||||
|
%%BeginDefaults
|
||||||
|
%%EndDefaults
|
||||||
|
|
||||||
|
%%BeginProlog
|
||||||
|
%
|
||||||
|
% Display a color image. The image is displayed in color on
|
||||||
|
% Postscript viewers or printers that support color, otherwise
|
||||||
|
% it is displayed as grayscale.
|
||||||
|
%
|
||||||
|
/DirectClassPacket
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% Get a DirectClass packet.
|
||||||
|
%
|
||||||
|
% Parameters:
|
||||||
|
% red.
|
||||||
|
% green.
|
||||||
|
% blue.
|
||||||
|
% length: number of pixels minus one of this color (optional).
|
||||||
|
%
|
||||||
|
currentfile color_packet readhexstring pop pop
|
||||||
|
compression 0 eq
|
||||||
|
{
|
||||||
|
/number_pixels 3 def
|
||||||
|
}
|
||||||
|
{
|
||||||
|
currentfile byte readhexstring pop 0 get
|
||||||
|
/number_pixels exch 1 add 3 mul def
|
||||||
|
} ifelse
|
||||||
|
0 3 number_pixels 1 sub
|
||||||
|
{
|
||||||
|
pixels exch color_packet putinterval
|
||||||
|
} for
|
||||||
|
pixels 0 number_pixels getinterval
|
||||||
|
} bind def
|
||||||
|
|
||||||
|
/DirectClassImage
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% Display a DirectClass image.
|
||||||
|
%
|
||||||
|
systemdict /colorimage known
|
||||||
|
{
|
||||||
|
columns rows 8
|
||||||
|
[
|
||||||
|
columns 0 0
|
||||||
|
rows neg 0 rows
|
||||||
|
]
|
||||||
|
{ DirectClassPacket } false 3 colorimage
|
||||||
|
}
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% No colorimage operator; convert to grayscale.
|
||||||
|
%
|
||||||
|
columns rows 8
|
||||||
|
[
|
||||||
|
columns 0 0
|
||||||
|
rows neg 0 rows
|
||||||
|
]
|
||||||
|
{ GrayDirectClassPacket } image
|
||||||
|
} ifelse
|
||||||
|
} bind def
|
||||||
|
|
||||||
|
/GrayDirectClassPacket
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% Get a DirectClass packet; convert to grayscale.
|
||||||
|
%
|
||||||
|
% Parameters:
|
||||||
|
% red
|
||||||
|
% green
|
||||||
|
% blue
|
||||||
|
% length: number of pixels minus one of this color (optional).
|
||||||
|
%
|
||||||
|
currentfile color_packet readhexstring pop pop
|
||||||
|
color_packet 0 get 0.299 mul
|
||||||
|
color_packet 1 get 0.587 mul add
|
||||||
|
color_packet 2 get 0.114 mul add
|
||||||
|
cvi
|
||||||
|
/gray_packet exch def
|
||||||
|
compression 0 eq
|
||||||
|
{
|
||||||
|
/number_pixels 1 def
|
||||||
|
}
|
||||||
|
{
|
||||||
|
currentfile byte readhexstring pop 0 get
|
||||||
|
/number_pixels exch 1 add def
|
||||||
|
} ifelse
|
||||||
|
0 1 number_pixels 1 sub
|
||||||
|
{
|
||||||
|
pixels exch gray_packet put
|
||||||
|
} for
|
||||||
|
pixels 0 number_pixels getinterval
|
||||||
|
} bind def
|
||||||
|
|
||||||
|
/GrayPseudoClassPacket
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% Get a PseudoClass packet; convert to grayscale.
|
||||||
|
%
|
||||||
|
% Parameters:
|
||||||
|
% index: index into the colormap.
|
||||||
|
% length: number of pixels minus one of this color (optional).
|
||||||
|
%
|
||||||
|
currentfile byte readhexstring pop 0 get
|
||||||
|
/offset exch 3 mul def
|
||||||
|
/color_packet colormap offset 3 getinterval def
|
||||||
|
color_packet 0 get 0.299 mul
|
||||||
|
color_packet 1 get 0.587 mul add
|
||||||
|
color_packet 2 get 0.114 mul add
|
||||||
|
cvi
|
||||||
|
/gray_packet exch def
|
||||||
|
compression 0 eq
|
||||||
|
{
|
||||||
|
/number_pixels 1 def
|
||||||
|
}
|
||||||
|
{
|
||||||
|
currentfile byte readhexstring pop 0 get
|
||||||
|
/number_pixels exch 1 add def
|
||||||
|
} ifelse
|
||||||
|
0 1 number_pixels 1 sub
|
||||||
|
{
|
||||||
|
pixels exch gray_packet put
|
||||||
|
} for
|
||||||
|
pixels 0 number_pixels getinterval
|
||||||
|
} bind def
|
||||||
|
|
||||||
|
/PseudoClassPacket
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% Get a PseudoClass packet.
|
||||||
|
%
|
||||||
|
% Parameters:
|
||||||
|
% index: index into the colormap.
|
||||||
|
% length: number of pixels minus one of this color (optional).
|
||||||
|
%
|
||||||
|
currentfile byte readhexstring pop 0 get
|
||||||
|
/offset exch 3 mul def
|
||||||
|
/color_packet colormap offset 3 getinterval def
|
||||||
|
compression 0 eq
|
||||||
|
{
|
||||||
|
/number_pixels 3 def
|
||||||
|
}
|
||||||
|
{
|
||||||
|
currentfile byte readhexstring pop 0 get
|
||||||
|
/number_pixels exch 1 add 3 mul def
|
||||||
|
} ifelse
|
||||||
|
0 3 number_pixels 1 sub
|
||||||
|
{
|
||||||
|
pixels exch color_packet putinterval
|
||||||
|
} for
|
||||||
|
pixels 0 number_pixels getinterval
|
||||||
|
} bind def
|
||||||
|
|
||||||
|
/PseudoClassImage
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% Display a PseudoClass image.
|
||||||
|
%
|
||||||
|
% Parameters:
|
||||||
|
% class: 0-PseudoClass or 1-Grayscale.
|
||||||
|
%
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /class exch def pop
|
||||||
|
class 0 gt
|
||||||
|
{
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /depth exch def pop
|
||||||
|
/grays columns 8 add depth sub depth mul 8 idiv string def
|
||||||
|
columns rows depth
|
||||||
|
[
|
||||||
|
columns 0 0
|
||||||
|
rows neg 0 rows
|
||||||
|
]
|
||||||
|
{ currentfile grays readhexstring pop } image
|
||||||
|
}
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% Parameters:
|
||||||
|
% colors: number of colors in the colormap.
|
||||||
|
% colormap: red, green, blue color packets.
|
||||||
|
%
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /colors exch def pop
|
||||||
|
/colors colors 3 mul def
|
||||||
|
/colormap colors string def
|
||||||
|
currentfile colormap readhexstring pop pop
|
||||||
|
systemdict /colorimage known
|
||||||
|
{
|
||||||
|
columns rows 8
|
||||||
|
[
|
||||||
|
columns 0 0
|
||||||
|
rows neg 0 rows
|
||||||
|
]
|
||||||
|
{ PseudoClassPacket } false 3 colorimage
|
||||||
|
}
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% No colorimage operator; convert to grayscale.
|
||||||
|
%
|
||||||
|
columns rows 8
|
||||||
|
[
|
||||||
|
columns 0 0
|
||||||
|
rows neg 0 rows
|
||||||
|
]
|
||||||
|
{ GrayPseudoClassPacket } image
|
||||||
|
} ifelse
|
||||||
|
} ifelse
|
||||||
|
} bind def
|
||||||
|
|
||||||
|
/DisplayImage
|
||||||
|
{
|
||||||
|
%
|
||||||
|
% Display a DirectClass or PseudoClass image.
|
||||||
|
%
|
||||||
|
% Parameters:
|
||||||
|
% x & y translation.
|
||||||
|
% x & y scale.
|
||||||
|
% label pointsize.
|
||||||
|
% image label.
|
||||||
|
% image columns & rows.
|
||||||
|
% class: 0-DirectClass or 1-PseudoClass.
|
||||||
|
% compression: 0-none or 1-RunlengthEncoded.
|
||||||
|
% hex color packets.
|
||||||
|
%
|
||||||
|
gsave
|
||||||
|
/buffer 512 string def
|
||||||
|
/byte 1 string def
|
||||||
|
/color_packet 3 string def
|
||||||
|
/pixels 768 string def
|
||||||
|
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /x exch def
|
||||||
|
token pop /y exch def pop
|
||||||
|
x y translate
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /x exch def
|
||||||
|
token pop /y exch def pop
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /pointsize exch def pop
|
||||||
|
x y scale
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /columns exch def
|
||||||
|
token pop /rows exch def pop
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /class exch def pop
|
||||||
|
currentfile buffer readline pop
|
||||||
|
token pop /compression exch def pop
|
||||||
|
class 0 gt { PseudoClassImage } { DirectClassImage } ifelse
|
||||||
|
grestore
|
||||||
|
showpage
|
||||||
|
} bind def
|
||||||
|
%%EndProlog
|
||||||
|
%%Page: 1 1
|
||||||
|
%%PageBoundingBox: 428 345 508 391
|
||||||
|
DisplayImage
|
||||||
|
428 345
|
||||||
|
80 46
|
||||||
|
12
|
||||||
|
80 46
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
8
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C
|
||||||
|
1C1C1C1C1C1C1C1C
|
||||||
|
%%PageTrailer
|
||||||
|
%%Trailer
|
||||||
|
%%EOF
|
@ -10,6 +10,7 @@ services:
|
|||||||
- ./uwsgi:/tmp/uwsgi
|
- ./uwsgi:/tmp/uwsgi
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
|
- spamassassin
|
||||||
environment:
|
environment:
|
||||||
MONGODB_HOST: db
|
MONGODB_HOST: db
|
||||||
SMTP_SERVER_ADDRESS: toto.mail
|
SMTP_SERVER_ADDRESS: toto.mail
|
||||||
@ -36,3 +37,7 @@ services:
|
|||||||
nginx_uid: 1000
|
nginx_uid: 1000
|
||||||
depends_on:
|
depends_on:
|
||||||
- mailer
|
- mailer
|
||||||
|
|
||||||
|
spamassassin:
|
||||||
|
image: dinkel/spamassassin
|
||||||
|
restart: unless-stopped
|
||||||
|
Loading…
Reference in New Issue
Block a user