Compare commits
No commits in common. "7e646d2ae95bad0b7e07cecf7fbcdb9ebda17186" and "b71d9e2ded2396e50f2d62e088ce315787cd2f6e" have entirely different histories.
7e646d2ae9
...
b71d9e2ded
@ -4,16 +4,13 @@ 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 spamassassin
|
RUN apk add python3-dev build-base linux-headers pcre-dev
|
||||||
RUN pip install uwsgi
|
RUN pip install uwsgi
|
||||||
#spamassassin_client
|
|
||||||
|
|
||||||
ENV UID=0
|
ENV UID=0
|
||||||
ENV MOUNT=/
|
ENV MOUNT=/
|
||||||
|
|
||||||
# Since the package maintainer doesnt merge PR
|
COPY ./main.py ./
|
||||||
# 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,7 +14,6 @@ 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 ############################################
|
||||||
@ -137,10 +136,7 @@ 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:
|
||||||
msg = build_mail(from_address, form['mail'], subject, content)
|
if not send_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
|
||||||
@ -182,7 +178,8 @@ 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 build_mail(from_address, to, subject, content):
|
def send_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)
|
||||||
@ -192,16 +189,8 @@ def build_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 sent. But only to stdout ----------------------------------')
|
print('------------------------------------ Following message wont be sent ------------------------------------')
|
||||||
print(msg.as_string())
|
print(msg.as_string())
|
||||||
print('--------------------------------------------------------------------------------------------------------')
|
print('--------------------------------------------------------------------------------------------------------')
|
||||||
return True
|
return True
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
Since the package maintainer doesnt merge PR
|
|
||||||
https://github.com/petermat/spamassassin_client/pull/2
|
|
@ -1,115 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,383 +0,0 @@
|
|||||||
%!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,7 +10,6 @@ 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
|
||||||
@ -37,7 +36,3 @@ 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