mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Moving back the stats module to the core. (#2011)
* Moving back the stats module to the core. * Added system packages to build RRDtool. * Fixed unit tests. * Improved coverage.
This commit is contained in:
+3
-1
@@ -22,6 +22,8 @@ addons:
|
||||
- ldap-utils
|
||||
- postfix
|
||||
- slapd
|
||||
- librrd-dev
|
||||
- rrdtool
|
||||
|
||||
cache: pip
|
||||
|
||||
@@ -50,7 +52,7 @@ before_script:
|
||||
script:
|
||||
- python ./tests.py
|
||||
- cd test_project
|
||||
- coverage run manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.transport modoboa.relaydomains modoboa.dnstools modoboa.ldapsync modoboa.policyd
|
||||
- coverage run manage.py test modoboa.core modoboa.lib modoboa.admin modoboa.limits modoboa.transport modoboa.relaydomains modoboa.dnstools modoboa.ldapsync modoboa.policyd modoboa.maillog
|
||||
|
||||
after_success:
|
||||
- coverage combine
|
||||
|
||||
@@ -16,6 +16,7 @@ class DomainFactory(PermissionFactory):
|
||||
model = models.Domain
|
||||
django_get_or_create = ("name", )
|
||||
|
||||
name = factory.Sequence(lambda n: "domain{}.test".format(n))
|
||||
type = "domain" # NOQA:A003
|
||||
quota = 0
|
||||
default_mailbox_quota = 10
|
||||
|
||||
@@ -172,9 +172,12 @@ Domains.prototype = {
|
||||
if (this.navobj.getbaseurl() === "list") {
|
||||
args.objtype = "domain";
|
||||
this.options.eor_message = gettext("No more domain to show");
|
||||
} else {
|
||||
} else if (this.navobj.getbaseurl() === "quota") {
|
||||
args.objtype = "quota";
|
||||
this.options.eor_message = gettext("No more quota to show");
|
||||
} else {
|
||||
args.objtype = "log";
|
||||
this.options.eor_message = gettext("No more log to show");
|
||||
}
|
||||
return args;
|
||||
},
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{% load i18n %}
|
||||
<th class="sortable" data-sort_order="queue_id">{% trans "Queue ID" %}</th>
|
||||
<th class="sortable" data-sort_order="date">{% trans "Date" %}</th>
|
||||
<th class="sortable" data-sort_order="sender">{% trans "From" %}</th>
|
||||
<th class="sortable" data-sort_order="rcpt">{% trans "To" %}</th>
|
||||
<th class="sortable" data-sort_order="status">{% trans "Status" %}</th>
|
||||
@@ -0,0 +1,9 @@
|
||||
{% for log in logs %}
|
||||
<tr>
|
||||
<td>{{ log.queue_id }}</td>
|
||||
<td>{{ log.date|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td><span title="{{ log.sender }}">{{ log.sender|truncatechars:30 }}</span></td>
|
||||
<td>{{ log.rcpt }}</td>
|
||||
<td>{{ log.status }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -36,10 +36,12 @@ def domains_menu(selection, user, ajax_mode=True):
|
||||
if ajax_mode:
|
||||
domain_list_url = "list/"
|
||||
quota_list_url = "quotas/"
|
||||
logs_url = "logs/"
|
||||
nav_classes += " ajaxnav"
|
||||
else:
|
||||
domain_list_url = reverse("admin:domain_list")
|
||||
quota_list_url = domain_list_url + "#quotas/"
|
||||
logs_url = domain_list_url + "#logs/"
|
||||
entries = [
|
||||
{"name": "domains",
|
||||
"label": _("List domains"),
|
||||
@@ -51,6 +53,11 @@ def domains_menu(selection, user, ajax_mode=True):
|
||||
"img": "fa fa-hdd-o",
|
||||
"class": "ajaxnav navigation",
|
||||
"url": quota_list_url},
|
||||
{"name": "logs",
|
||||
"label": _("Message logs"),
|
||||
"img": "fa fa-list",
|
||||
"class": "ajaxnav navigation",
|
||||
"url": logs_url},
|
||||
]
|
||||
if user.has_perm("admin.add_domain"):
|
||||
extra_entries = signals.extra_domain_menu_entries.send(
|
||||
|
||||
@@ -16,6 +16,8 @@ from modoboa.core import factories as core_factories
|
||||
from modoboa.core.models import User
|
||||
from modoboa.core.tests.test_views import SETTINGS_SAMPLE
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
from modoboa.maillog import factories as ml_factories
|
||||
|
||||
from . import utils
|
||||
from .. import factories
|
||||
from ..models import Alias, Domain
|
||||
@@ -336,6 +338,30 @@ class DomainTestCase(ModoTestCase):
|
||||
response = self.ajax_get("{}?sort_order=allocated_quota".format(url))
|
||||
self.assertNotEqual(old_rows, response["rows"])
|
||||
|
||||
def test_domain_logs_list_view(self):
|
||||
"""Test logs list view."""
|
||||
domain = Domain.objects.get(name="test.com")
|
||||
ml_factories.MaillogFactory(from_domain=domain)
|
||||
ml_factories.MaillogFactory(to_domain=domain, status="received")
|
||||
ml_factories.MaillogFactory()
|
||||
ml_factories.MaillogFactory()
|
||||
url = reverse("admin:domain_logs_list")
|
||||
response = self.ajax_get(url)
|
||||
self.assertIn("ID1", response["rows"])
|
||||
|
||||
old_rows = response["rows"]
|
||||
response = self.ajax_get("{}?sort_order=-sender".format(url))
|
||||
self.assertNotEqual(old_rows, response["rows"])
|
||||
|
||||
response = self.ajax_get("{}?searchquery=ID1".format(url))
|
||||
self.assertNotEqual(old_rows, response["rows"])
|
||||
|
||||
admin = User.objects.get(username="admin@test.com")
|
||||
self.client.force_login(admin)
|
||||
url = reverse("admin:domain_logs_list")
|
||||
response = self.ajax_get(url)
|
||||
self.assertNotEqual(old_rows, response["rows"])
|
||||
|
||||
def test_statitics_widget(self):
|
||||
"""Test statistics display in dashboard."""
|
||||
url = reverse("core:dashboard")
|
||||
|
||||
@@ -24,6 +24,8 @@ urlpatterns = [
|
||||
path('domains/list/', domain_views._domains, name="_domain_list"),
|
||||
path('domains/quotas/', domain_views.list_quotas,
|
||||
name="domain_quota_list"),
|
||||
path('domains/logs/', domain_views.list_logs,
|
||||
name="domain_logs_list"),
|
||||
path('domains/flatlist/', domain_views.domains_list,
|
||||
name="domain_flat_list"),
|
||||
path('domains/new/', domain_views.newdomain, name="domain_add"),
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.contrib.auth import mixins as auth_mixins
|
||||
from django.contrib.auth.decorators import (
|
||||
login_required, permission_required, user_passes_test
|
||||
)
|
||||
from django.db.models import Sum
|
||||
from django.db.models import Q, Sum
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
from django.template.loader import render_to_string
|
||||
@@ -21,6 +21,8 @@ from modoboa.core import signals as core_signals
|
||||
from modoboa.lib.exceptions import PermDeniedException
|
||||
from modoboa.lib.listing import get_listing_page, get_sort_order
|
||||
from modoboa.lib.web_utils import render_to_json_response
|
||||
from modoboa.maillog import models as ml_models
|
||||
|
||||
from .. import signals
|
||||
from ..forms import DomainForm, DomainWizard
|
||||
from ..lib import get_domains
|
||||
@@ -119,9 +121,12 @@ def domains(request, tplname="admin/domains.html"):
|
||||
)
|
||||
def get_next_page(request):
|
||||
"""Return the next page of the domain or quota list."""
|
||||
if request.GET.get("objtype", "domain") == "domain":
|
||||
objtype = request.GET.get("objtype", "domain")
|
||||
if objtype == "domain":
|
||||
return _domains(request)
|
||||
return list_quotas(request)
|
||||
if objtype == "quota":
|
||||
return list_quotas(request)
|
||||
return list_logs(request)
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -160,6 +165,43 @@ def list_quotas(request):
|
||||
return render_to_json_response(context)
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("admin.view_domain")
|
||||
def list_logs(request):
|
||||
"""List all Maillog entries."""
|
||||
sort_order, sort_dir = get_sort_order(request.GET, "date")
|
||||
search = request.GET.get("searchquery")
|
||||
if not request.user.is_superuser:
|
||||
domains = Domain.objects.get_for_admin(request.user)
|
||||
logs = ml_models.Maillog.objects.filter(
|
||||
Q(from_domain__in=domains) | Q(to_domain__in=domains)
|
||||
)
|
||||
else:
|
||||
logs = ml_models.Maillog.objects.all()
|
||||
logs = logs.order_by("{}{}".format(sort_dir, sort_order))
|
||||
if search:
|
||||
logs = logs.filter(
|
||||
Q(sender__icontains=search) |
|
||||
Q(rcpt__icontains=search) |
|
||||
Q(queue_id__icontains=search) |
|
||||
Q(status__icontains=search)
|
||||
)
|
||||
page = get_listing_page(logs, request.GET.get("page", 1))
|
||||
context = {
|
||||
"headers": render_to_string(
|
||||
"admin/domains_log_headers.html", {}, request
|
||||
)
|
||||
}
|
||||
if page is None:
|
||||
context["length"] = 0
|
||||
else:
|
||||
context["rows"] = render_to_string(
|
||||
"admin/domains_logs.html", {"logs": page}, request
|
||||
)
|
||||
context["pages"] = [page.number]
|
||||
return render_to_json_response(context)
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("admin.add_domain")
|
||||
@reversion.create_revision()
|
||||
|
||||
@@ -81,6 +81,7 @@ MODOBOA_APPS = (
|
||||
'modoboa.limits',
|
||||
'modoboa.parameters',
|
||||
'modoboa.dnstools',
|
||||
'modoboa.maillog',
|
||||
# Modoboa extensions here.
|
||||
{% for extension in extensions %} '{{ extension }}',
|
||||
{% endfor %}
|
||||
|
||||
@@ -89,7 +89,10 @@ SETTINGS_SAMPLE = {
|
||||
"core-sms_provider": "",
|
||||
"core-sms_ovh_endpoint": "ovh-eu",
|
||||
"core-password_recovery_msg": "",
|
||||
"core-ldap_dovecot_sync": False
|
||||
"core-ldap_dovecot_sync": False,
|
||||
"maillog-logfile": "/var/log/mail.log",
|
||||
"maillog-rrd_rootdir": "/tmp",
|
||||
"maillog-greylist": False,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
default_app_config = "modoboa.maillog.apps.MaillogConfig"
|
||||
@@ -0,0 +1,16 @@
|
||||
"""AppConfig for stats."""
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
from .forms import load_settings
|
||||
|
||||
|
||||
class MaillogConfig(AppConfig):
|
||||
"""App configuration."""
|
||||
|
||||
name = "modoboa.maillog"
|
||||
verbose_name = "Modoboa graphical statistics"
|
||||
|
||||
def ready(self):
|
||||
load_settings()
|
||||
from . import handlers
|
||||
@@ -0,0 +1,25 @@
|
||||
"""App. factories."""
|
||||
|
||||
import factory
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
from modoboa.admin import factories as admin_factories
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
class MaillogFactory(factory.DjangoModelFactory):
|
||||
"""Factory class for Maillog."""
|
||||
|
||||
class Meta:
|
||||
model = models.Maillog
|
||||
|
||||
queue_id = factory.Sequence(lambda n: "ID{}".format(n))
|
||||
date = timezone.now()
|
||||
sender = factory.Sequence(lambda n: "sender{}@example.test".format(n))
|
||||
rcpt = factory.Sequence(lambda n: "rcpt{}@example2.test".format(n))
|
||||
size = 100
|
||||
status = "sent"
|
||||
from_domain = factory.SubFactory(admin_factories.DomainFactory)
|
||||
to_domain = factory.SubFactory(admin_factories.DomainFactory)
|
||||
@@ -0,0 +1,59 @@
|
||||
"""Modoboa stats forms."""
|
||||
|
||||
import rrdtool
|
||||
|
||||
from pkg_resources import parse_version
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from django import forms
|
||||
|
||||
from modoboa.lib import form_utils
|
||||
from modoboa.parameters import forms as param_forms
|
||||
|
||||
|
||||
class ParametersForm(param_forms.AdminParametersForm):
|
||||
"""Stats global parameters."""
|
||||
|
||||
app = "maillog"
|
||||
|
||||
general_sep = form_utils.SeparatorField(label=ugettext_lazy("General"))
|
||||
|
||||
logfile = forms.CharField(
|
||||
label=ugettext_lazy("Path to the log file"),
|
||||
initial="/var/log/mail.log",
|
||||
help_text=ugettext_lazy("Path to log file used to collect statistics"),
|
||||
widget=forms.TextInput(attrs={"class": "form-control"})
|
||||
)
|
||||
|
||||
rrd_rootdir = forms.CharField(
|
||||
label=ugettext_lazy("Directory to store RRD files"),
|
||||
initial="/tmp/modoboa",
|
||||
help_text=ugettext_lazy(
|
||||
"Path to directory where RRD files are stored"),
|
||||
widget=forms.TextInput(attrs={"class": "form-control"})
|
||||
)
|
||||
|
||||
greylist = form_utils.YesNoField(
|
||||
label=ugettext_lazy("Show greylisted messages"),
|
||||
initial=False,
|
||||
help_text=ugettext_lazy(
|
||||
"Differentiate between hard and soft rejects (greylisting)")
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Check RRDtool version."""
|
||||
super().__init__(*args, **kwargs)
|
||||
rrd_version = parse_version(rrdtool.lib_version())
|
||||
required_version = parse_version("1.6.0")
|
||||
test_mode = getattr(settings, "RRDTOOL_TEST_MODE", False)
|
||||
if rrd_version < required_version and not test_mode:
|
||||
del self.fields["greylist"]
|
||||
|
||||
|
||||
def load_settings():
|
||||
"""Load app settings."""
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
param_tools.registry.add(
|
||||
"global", ParametersForm, ugettext_lazy("Statistics"))
|
||||
@@ -0,0 +1,269 @@
|
||||
"""Classes to define graphics."""
|
||||
|
||||
import inspect
|
||||
from itertools import chain
|
||||
import os
|
||||
|
||||
from lxml import etree
|
||||
import six
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.encoding import smart_bytes, smart_text
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.lib import exceptions
|
||||
from modoboa.lib.sysutils import exec_cmd
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
|
||||
class Curve:
|
||||
|
||||
"""Graphic curve.
|
||||
|
||||
Simple way to represent a graphic curve.
|
||||
"""
|
||||
|
||||
def __init__(self, dsname, color, legend, cfunc="AVERAGE"):
|
||||
"""Constructor.
|
||||
"""
|
||||
self.dsname = dsname
|
||||
self.color = color
|
||||
self.legend = legend
|
||||
self.cfunc = cfunc
|
||||
|
||||
def to_rrd_command_args(self, rrdfile):
|
||||
"""Convert this curve to the approriate RRDtool command.
|
||||
|
||||
:param str rrdfile: RRD file name
|
||||
:return: a list
|
||||
"""
|
||||
rrdfile = os.path.join(
|
||||
param_tools.get_global_parameter("rrd_rootdir"), "%s.rrd" % rrdfile
|
||||
)
|
||||
return [
|
||||
'DEF:%s=%s:%s:%s' %
|
||||
(self.dsname, rrdfile, self.dsname, self.cfunc),
|
||||
'CDEF:%(ds)spm=%(ds)s,UN,0,%(ds)s,IF,60,*' % {"ds": self.dsname},
|
||||
'XPORT:%spm:"%s"' % (self.dsname, self.legend)
|
||||
]
|
||||
|
||||
|
||||
class Graphic:
|
||||
"""Graphic."""
|
||||
|
||||
def __init__(self):
|
||||
"""Constructor."""
|
||||
self._curves = []
|
||||
try:
|
||||
order = getattr(self, "order")
|
||||
except AttributeError:
|
||||
for member in inspect.getmembers(self):
|
||||
if isinstance(member[1], Curve):
|
||||
self._curves += [member[1]]
|
||||
else:
|
||||
for name in order:
|
||||
try:
|
||||
curve = getattr(self, name)
|
||||
except AttributeError:
|
||||
continue
|
||||
if not isinstance(curve, Curve):
|
||||
continue
|
||||
self._curves += [curve]
|
||||
|
||||
@property
|
||||
def display_name(self):
|
||||
return self.__class__.__name__.lower()
|
||||
|
||||
@property
|
||||
def rrdtool_binary(self):
|
||||
"""Return path to rrdtool binary."""
|
||||
dpath = None
|
||||
code, output = exec_cmd("which rrdtool")
|
||||
if not code:
|
||||
dpath = output.strip()
|
||||
else:
|
||||
known_paths = getattr(
|
||||
settings, "RRDTOOL_LOOKUP_PATH",
|
||||
("/usr/bin/rrdtool", "/usr/local/bin/rrdtool")
|
||||
)
|
||||
for fpath in known_paths:
|
||||
if os.path.isfile(fpath) and os.access(fpath, os.X_OK):
|
||||
dpath = fpath
|
||||
if dpath is None:
|
||||
raise exceptions.InternalError(
|
||||
_("Failed to locate rrdtool binary."))
|
||||
return smart_text(dpath)
|
||||
|
||||
def export(self, rrdfile, start, end):
|
||||
"""Export data to XML using rrdtool and convert it to JSON."""
|
||||
result = []
|
||||
cmdargs = []
|
||||
for curve in self._curves:
|
||||
result += [{
|
||||
"name": str(curve.legend),
|
||||
"color": curve.color, "data": []
|
||||
}]
|
||||
cmdargs += curve.to_rrd_command_args(rrdfile)
|
||||
code = 0
|
||||
|
||||
cmd = "{} xport --start {} --end {} ".format(
|
||||
self.rrdtool_binary, str(start), str(end))
|
||||
cmd += " ".join(cmdargs)
|
||||
code, output = exec_cmd(smart_bytes(cmd))
|
||||
if code:
|
||||
return []
|
||||
|
||||
tree = etree.fromstring(output)
|
||||
timestamp = int(tree.xpath('/xport/meta/start')[0].text)
|
||||
step = int(tree.xpath('/xport/meta/step')[0].text)
|
||||
for row in tree.xpath('/xport/data/row'):
|
||||
for vindex, value in enumerate(row.findall('v')):
|
||||
if value.text == 'NaN':
|
||||
result[vindex]['data'].append({'x': timestamp, 'y': 0})
|
||||
else:
|
||||
result[vindex]['data'].append(
|
||||
{'x': timestamp, 'y': float(value.text)}
|
||||
)
|
||||
timestamp += step
|
||||
return result
|
||||
|
||||
|
||||
class GraphicSet(object):
|
||||
"""A set of graphics."""
|
||||
|
||||
domain_selector = False
|
||||
title = None
|
||||
_graphics = []
|
||||
|
||||
def __init__(self, instances=None):
|
||||
if instances is None:
|
||||
instances = []
|
||||
self.__ginstances = instances
|
||||
|
||||
@property
|
||||
def html_id(self):
|
||||
return self.__class__.__name__.lower()
|
||||
|
||||
@property
|
||||
def graphics(self):
|
||||
if not self.__ginstances:
|
||||
self.__ginstances = [graphic() for graphic in self._graphics]
|
||||
return self.__ginstances
|
||||
|
||||
def get_graphic_names(self):
|
||||
return [graphic.display_name for graphic in self._graphics]
|
||||
|
||||
def get_file_name(self, request):
|
||||
"""Return database file name."""
|
||||
return self.file_name
|
||||
|
||||
def export(self, rrdfile, start, end):
|
||||
result = {}
|
||||
for graph in self.graphics:
|
||||
result[graph.display_name] = {
|
||||
"title": six.text_type(graph.title),
|
||||
"curves": graph.export(rrdfile, start, end)
|
||||
}
|
||||
return result
|
||||
|
||||
|
||||
class AverageTraffic(Graphic):
|
||||
"""Average traffic."""
|
||||
|
||||
title = ugettext_lazy('Average traffic (msgs/min)')
|
||||
|
||||
# Curve definitions
|
||||
sent = Curve("sent", "lawngreen", ugettext_lazy("sent messages"))
|
||||
recv = Curve("recv", "steelblue", ugettext_lazy("received messages"))
|
||||
bounced = Curve("bounced", "yellow", ugettext_lazy("bounced messages"))
|
||||
reject = Curve("reject", "tomato", ugettext_lazy("rejected messages"))
|
||||
virus = Curve("virus", "orange", ugettext_lazy("virus messages"))
|
||||
spam = Curve("spam", "silver", ugettext_lazy("spam messages"))
|
||||
|
||||
order = ["reject", "bounced", "recv", "sent", "virus", "spam"]
|
||||
|
||||
def __init__(self, greylist=False):
|
||||
if greylist:
|
||||
self.greylist = Curve(
|
||||
"greylist", "dimgrey", ugettext_lazy("greylisted messages"))
|
||||
self.order = [
|
||||
"reject", "greylist", "bounced", "recv", "sent", "virus",
|
||||
"spam"
|
||||
]
|
||||
super().__init__()
|
||||
|
||||
|
||||
class AverageTrafficSize(Graphic):
|
||||
"""Average traffic size."""
|
||||
|
||||
title = ugettext_lazy('Average normal traffic size (bytes/min)')
|
||||
|
||||
# Curve definitions
|
||||
size_recv = Curve("size_recv", "orange", ugettext_lazy("received size"))
|
||||
size_sent = Curve(
|
||||
"size_sent", "mediumturquoise", ugettext_lazy("sent size")
|
||||
)
|
||||
|
||||
|
||||
class MailTraffic(GraphicSet):
|
||||
"""Mail traffic graphic set."""
|
||||
|
||||
domain_selector = True
|
||||
title = ugettext_lazy("Mail traffic")
|
||||
_graphics = [AverageTraffic, AverageTrafficSize]
|
||||
|
||||
def __init__(self, greylist=False):
|
||||
instances = [AverageTraffic(greylist), AverageTrafficSize()]
|
||||
super().__init__(instances)
|
||||
|
||||
def _check_domain_access(self, user, pattern):
|
||||
"""Check if an administrator can access a domain.
|
||||
|
||||
If a non super administrator asks for the global view, we give him
|
||||
a view on the first domain he manage instead.
|
||||
|
||||
:return: a domain name (str) or None.
|
||||
"""
|
||||
if pattern in [None, "global"]:
|
||||
if not user.is_superuser:
|
||||
domains = admin_models.Domain.objects.get_for_admin(user)
|
||||
if not domains.exists():
|
||||
return None
|
||||
return domains.first().name
|
||||
return "global"
|
||||
|
||||
results = list(
|
||||
chain(
|
||||
admin_models.Domain.objects.filter(name__startswith=pattern),
|
||||
admin_models.DomainAlias.objects.filter(
|
||||
name__startswith=pattern)
|
||||
)
|
||||
)
|
||||
if len(results) != 1:
|
||||
return None
|
||||
if not user.can_access(results[0]):
|
||||
raise exceptions.PermDeniedException
|
||||
return results[0].name
|
||||
|
||||
def get_file_name(self, request):
|
||||
"""Retrieve file name according to user and args."""
|
||||
searchq = request.GET.get("searchquery", None)
|
||||
return self._check_domain_access(request.user, searchq)
|
||||
|
||||
|
||||
class AccountCreationGraphic(Graphic):
|
||||
"""Account creation over time."""
|
||||
|
||||
title = ugettext_lazy("Average account creation (account/hour)")
|
||||
|
||||
accounts = Curve(
|
||||
"new_accounts", "steelblue", ugettext_lazy("New accounts"))
|
||||
|
||||
|
||||
class AccountGraphicSet(GraphicSet):
|
||||
"""A graphic set for accounts."""
|
||||
|
||||
file_name = "new_accounts"
|
||||
title = ugettext_lazy("Accounts")
|
||||
_graphics = [AccountCreationGraphic]
|
||||
@@ -0,0 +1,38 @@
|
||||
"""Modoboa stats signal handlers."""
|
||||
|
||||
from django.urls import reverse
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from modoboa.admin import signals as admin_signals
|
||||
from modoboa.core import signals as core_signals
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
from . import graphics
|
||||
from . import signals
|
||||
|
||||
|
||||
@receiver(core_signals.extra_user_menu_entries)
|
||||
def menu(sender, location, user, **kwargs):
|
||||
"""Return extra menu entry."""
|
||||
if location != "top_menu" or user.role == "SimpleUsers":
|
||||
return []
|
||||
return [
|
||||
{"name": "stats",
|
||||
"label": _("Statistics"),
|
||||
"url": reverse('maillog:fullindex')}
|
||||
]
|
||||
|
||||
|
||||
@receiver(signals.get_graph_sets)
|
||||
def get_default_graphic_sets(sender, **kwargs):
|
||||
"""Return graphic set."""
|
||||
mail_traffic_gset = graphics.MailTraffic(
|
||||
param_tools.get_global_parameter("greylist", raise_exception=False))
|
||||
result = {
|
||||
mail_traffic_gset.html_id: mail_traffic_gset
|
||||
}
|
||||
if kwargs.get("user").is_superuser:
|
||||
account_gset = graphics.AccountGraphicSet()
|
||||
result.update({account_gset.html_id: account_gset})
|
||||
return result
|
||||
@@ -0,0 +1,25 @@
|
||||
# coding: utf-8
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def date_to_timestamp(timetuple):
|
||||
"""Date conversion.
|
||||
|
||||
Returns a date and a time in seconds from the epoch.
|
||||
|
||||
:param list timetuple: list containing date
|
||||
:return: an integer
|
||||
"""
|
||||
date = " ".join(
|
||||
[("%d" % elem) if isinstance(elem, int) else elem
|
||||
for elem in timetuple]
|
||||
)
|
||||
fmt = "%Y %m %d %H %M %S" \
|
||||
if timetuple[1].isdigit() else "%Y %b %d %H %M %S"
|
||||
try:
|
||||
local = time.strptime(date, fmt)
|
||||
except ValueError:
|
||||
print >> sys.stderr, "Error: failed to convert date and time"
|
||||
return 0
|
||||
return int(time.mktime(local))
|
||||
@@ -0,0 +1,178 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Miroslav Abrahám <miris@kunago.com>, 2013-2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2015-01-06 10:05+0000\n"
|
||||
"Last-Translator: Miroslav Abrahám <miris@kunago.com>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/cs_CZ/)\n"
|
||||
"Language: cs_CZ\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Obecné"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Cesta k souboru záznamů"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr ""
|
||||
"Cesta k souboru záznamů, který se používá pro sběr statistických informací"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Adresář pro RRD soubory"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Cesta k adresáři, ve kterém budou ukládány RRD soubory"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "odmítnuté zprávy"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiky"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Průměrný provoz (zprávy/min)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "odeslané zprávy"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "přijaté zprávy"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "nedoručené zprávy"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "odmítnuté zprávy"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "odeslané zprávy"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "odeslané zprávy"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "odmítnuté zprávy"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Průměrná velikost provozu (bajtů/min)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "doručená velikost"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "odeslaná velikost"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Provoz emailů"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Grafické statistiky"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Hledat doménu"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Uložit"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Žádné statistiky nejsou dostupné"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Den"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Týden"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Měsíc"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Rok"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Vlastní"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Nastaveno neznámé zobrazení"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Nastaveno neznámé zobrazení"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Neplatně nastavený vlastní časový interval"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Grafické statistiky emailového provozu s použitím RRDtool"
|
||||
@@ -0,0 +1,24 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Miroslav Abrahám <miris@kunago.com>, 2013,2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2015-01-06 10:05+0000\n"
|
||||
"Last-Translator: Miroslav Abrahám <miris@kunago.com>\n"
|
||||
"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/cs_CZ/)\n"
|
||||
"Language: cs_CZ\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Vyhledat doménu"
|
||||
@@ -0,0 +1,178 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Arvedui <arvedui@posteo.de>, 2014
|
||||
# Patrick Koetter <p@state-of-mind.de>, 2010
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2014-12-03 11:02+0000\n"
|
||||
"Last-Translator: Arvedui <arvedui@posteo.de>\n"
|
||||
"Language-Team: German (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"de/)\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Allgemein"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Pfad zur Log-Datei"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Pfad zur Log-Datei, um Statistiken zu sammeln"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Ablageverzeichnis für RRD-Dateien"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Pfad zum Verzeichnis in dem die RRD-Dateien abgelegt werden"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "Abgewiesene Nachrichten"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiken"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Durchschnittlicher Traffic (Nachrichten/min)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "Gesendete Nachrichten"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "Empfangene Nachrichten"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "Zurückgeworfene Nachrichten"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "Abgewiesene Nachrichten"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "Gesendete Nachrichten"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "Gesendete Nachrichten"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "Abgewiesene Nachrichten"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Durchschnittliche Traffic-Menge (Bytes/min)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "Empfangsgröße"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "Versendegröße"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Mailverkehr"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Grafische Statistiken"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Domain suchen"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Antworten"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Keine Statistik-Daten verfügbar"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Tag"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Woche"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Monat"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Jahr"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Benutzerdefiniert"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Unbekanntes graphisches Set"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Unbekanntes graphisches Set"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Ungültiger individueller Zeitraum"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Grafische E-Mail-Statistik (setzt RRDtool ein)"
|
||||
@@ -0,0 +1,25 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Arvedui <arvedui@posteo.de>, 2014
|
||||
# Patrick Koetter <p@state-of-mind.de>, 2010
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2014-12-01 12:12+0000\n"
|
||||
"Last-Translator: Arvedui <arvedui@posteo.de>\n"
|
||||
"Language-Team: German (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"de/)\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Domain suchen"
|
||||
@@ -0,0 +1,176 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Giannis Kapetanakis <bilias@edu.physics.uoc.gr>, 2016
|
||||
# Kostas Moumouris <moumouriskostas@gmail.com>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2017-10-12 07:37+0000\n"
|
||||
"Last-Translator: Kostas Moumouris <moumouriskostas@gmail.com>\n"
|
||||
"Language-Team: Greek (Greece) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/el_GR/)\n"
|
||||
"Language: el_GR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Γενικά"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Διαδρομή προς το αρχείο καταγραφής"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Διαδρομή προς το αρχείο καταγραφής για την συλλογή στατιστικών"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Κατάλογος αρχείων για την αποθήκευση των αρχείων RRD"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Διαδρομή προς τον κατάλογο αρχείων για την αποθήκευση αρχείων RRD"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "Εμφάνιση μηνυμάτων greylisted"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
"Διαφοροποίηση μεταξύ σκληρών (hard) και μαλακών (soft) απορρίψεων "
|
||||
"(greylisting)"
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Στατιστικά"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr "Αδυναμία εύρεσης του εκτελέσουμε rrdtool."
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Μέσος όρος κίνησης (μηνύματα/λεπτό)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "απεσταλμένα μηνύματα"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "ληφθέντα μηνήματα"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "Μηνύματα bounced "
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "απορριφθέντα μηνύματα"
|
||||
|
||||
#: graphics.py:181
|
||||
msgid "virus messages"
|
||||
msgstr ""
|
||||
"Μηνύματα με ιούς \n"
|
||||
" "
|
||||
|
||||
#: graphics.py:182
|
||||
msgid "spam messages"
|
||||
msgstr "Διαφημιστικά μηνύματα"
|
||||
|
||||
#: graphics.py:189
|
||||
msgid "greylisted messages"
|
||||
msgstr ""
|
||||
"Μηνύματα που είναι greylisted\n"
|
||||
" "
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Μέσος όρος φυσιολογικού traffic (bytes/min) "
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "Μέγεθος λαμβανόμενου"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "μέγεθος αποστολής"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Κίνηση Mail"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr "Μέσος όρος δημιουργίας λογαριασμών (λογαριασμοί/ώρα)"
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr "Νέοι λογαριασμοί"
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr "Λογαριασμοί"
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Γραφικά στατιστικά"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Αναζήτηση ενός domain"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Εφαρμογή"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Δεν υπάρχουν διαθέσιμα στατιστικά"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Ημέρα"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Εβδομάδα"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Μήνας"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Έτος"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Προσαρμοσμένο"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Άγνωστο σετ γραφικών"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Άγνωστο σετ γραφικών"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Λάθος προσαρμοσμένη περίοδος"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Γραφικά στατιστικά της κίνησης email με RRDtool"
|
||||
@@ -0,0 +1,23 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Giannis Kapetanakis <bilias@edu.physics.uoc.gr>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 22:21+0000\n"
|
||||
"Last-Translator: Giannis Kapetanakis <bilias@edu.physics.uoc.gr>\n"
|
||||
"Language-Team: Greek (Greece) (http://www.transifex.com/tonio/modoboa/language/el_GR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: el_GR\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Αναζήτηση ενός domain"
|
||||
@@ -0,0 +1,162 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Show greylisted messages"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:181
|
||||
msgid "virus messages"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:182
|
||||
msgid "spam messages"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:189
|
||||
msgid "greylisted messages"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:68
|
||||
msgid "Unknown domain"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,22 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr ""
|
||||
@@ -0,0 +1,171 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Carlos L <carlos.latorre.sanchez@openmailbox.org>, 2017
|
||||
# Evilham <github@evilham.com>, 2017
|
||||
# Pedro Gracia <lasarux@neuroomante.com>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2017-11-23 16:41+0000\n"
|
||||
"Last-Translator: Evilham <github@evilham.com>\n"
|
||||
"Language-Team: Spanish (http://www.transifex.com/tonio/modoboa/language/"
|
||||
"es/)\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "General"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Ruta del fichero de log"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Ruta al fichero de log usado para recolectar estadísticas"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Directorio para guardar los ficheros RRD"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Ruta al directorio dónde están almacenados los ficheros RRD"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Show greylisted messages"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Estadísticas"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr "Fallo al localizar el binario rrdtool"
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Media del tráfico (msgs/min)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "mensajes enviados"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "mensajes recibidos"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "mensajes rebotados"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "mensajes bloqueados"
|
||||
|
||||
#: graphics.py:181
|
||||
msgid "virus messages"
|
||||
msgstr "mensajes con virus"
|
||||
|
||||
#: graphics.py:182
|
||||
msgid "spam messages"
|
||||
msgstr "Mensajes Basura"
|
||||
|
||||
#: graphics.py:189
|
||||
msgid "greylisted messages"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Media normal del tamaño del tráfico (bytes/min)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "tamaño recibido"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "tamaño enviado"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Tráfico de correo"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr "Creación promedio de cuentas (cuentas/hora)"
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr "Cuentas nuevos"
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr "Cuentas"
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Estadísticas gráficas"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Buscar un dominio"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Aplicar"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "No hay estadísticas disponibles"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Día"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Semana"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Mes"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Año"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "A medida"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Conjunto gráfico desconocido"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Conjunto gráfico desconocido"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Período elegido erróneo"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Estadísticas gráficas del tráfico de emails usando RRDtool"
|
||||
@@ -0,0 +1,24 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Pedro Gracia <lasarux@neuroomante.com>, 2011,2013
|
||||
# Pedro Gracia <pedro.gracia@impulzia.com>, 2010-2011
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:57+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Spanish (http://www.transifex.com/tonio/modoboa/language/es/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: es\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Buscar un dominio"
|
||||
@@ -0,0 +1,170 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2017-08-09 08:17+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: French (http://www.transifex.com/tonio/modoboa/language/fr/)\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Général"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Chemin d'accès vers le journal"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Emplacement du log utilisé pour collecter les statistiques"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Répertoire où stocker les fichiers RRD"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Emplacement du répertoire de stockage des fichiers RRD"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "Afficher les messages greylistés"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr "Différencie les rejets en douceur des rejets durs (greylisting)"
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiques"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr "Impossible de trouver le binaire rrdtool"
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Trafic moyen (msgs/min)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "messages envoyés"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "messages reçus"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "messages non remis"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "messages rejetés"
|
||||
|
||||
#: graphics.py:181
|
||||
msgid "virus messages"
|
||||
msgstr "messages de type virus"
|
||||
|
||||
#: graphics.py:182
|
||||
msgid "spam messages"
|
||||
msgstr "messages de type spam"
|
||||
|
||||
#: graphics.py:189
|
||||
msgid "greylisted messages"
|
||||
msgstr "Messages greylistés"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Taille moyenne du trafic normal (octets/min)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "taille reçue"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "taille envoyée"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Trafic messagerie"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr "Moyenne des créations de compte (compte/heure)"
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr "Nouveaux comptes"
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr "Comptes"
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Statistiques graphiques"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Chercher un domaine"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Appliquer"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Aucune statistique disponible"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Jour"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Semaine"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Mois"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Année"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Personnalisée"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Jeu de graphiques inconnu"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Jeu de graphiques inconnu"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Mauvaise période personnalisée"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr ""
|
||||
#~ "Statistiques graphiques concernant le trafic des messages utilisant "
|
||||
#~ "RRDtool"
|
||||
@@ -0,0 +1,22 @@
|
||||
# Modoboa french translation
|
||||
# Copyright (C) 2009-2013
|
||||
# This file is distributed under the same license as the Modoboa package.
|
||||
# Antoine Nguyen <tonio@ngyn.org>, 2009-2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: modoboa-1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2011-01-07 10:00+0100\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: FR <tonio@ngyn.org>\n"
|
||||
"Language: Français\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Checher un domaine"
|
||||
@@ -0,0 +1,177 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Giancarlo Gaifas <lallo@artiemestieri.tn.it>, 2013.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2013-12-23 00:56+0100\n"
|
||||
"Last-Translator: Alberto Berti <alberto@metapensiero.it>\n"
|
||||
"Language-Team: ITALIANO <LL@li.org>\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Generale"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Percorso del file di log"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Percorso del file di log utilizzato per raccogliere le statistiche"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Cartella dei file RRD"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Percorso della cartella dove sono memorizzati i file RRD"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "messaggi respinti"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Statistiche"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
#, fuzzy
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Dimensione del traffico normale medio"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "messaggi inviati"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "messaggi ricevuti"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "messaggi di rimbalzo"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "messaggi respinti"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "messaggi inviati"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "messaggi inviati"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "messaggi respinti"
|
||||
|
||||
#: graphics.py:200
|
||||
#, fuzzy
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Dimensione del traffico normale medio"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "dimensione di ricezione"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "dimensione di spedizione"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Traffico mail"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Grafico statistiche"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Ricerca un dominio"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Applica"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Non sono disponibili statistiche"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Giorno"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Settimana"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Mese"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Anno"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Impostazione grafica sconosciuta"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Impostazione grafica sconosciuta"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Periodo personalizzato sbagliato"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Grafico delle statistiche sul traffico e-mail utilizzando RRDtool"
|
||||
@@ -0,0 +1,22 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2013-12-23 00:58+0100\n"
|
||||
"Last-Translator: Alberto Berti <alberto@metapensiero.it>\n"
|
||||
"Language-Team: Italiano <LL@li.org>\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Cerca un dominio"
|
||||
@@ -0,0 +1,179 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# cwatanab <chihiro.watanabe@live.jp>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2016-06-07 08:56+0000\n"
|
||||
"Last-Translator: cwatanab <chihiro.watanabe@live.jp>\n"
|
||||
"Language-Team: Japanese (Japan) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/ja_JP/)\n"
|
||||
"Language: ja_JP\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "全般"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "ログファイルへのパス"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "統計情報を収集するために使用されたログファイルへのパス"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "RRD ファイルを保管するためのディレクトリ"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "RRD ファイルが保管されたディレクトリへのパス"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "拒否メッセージ"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "統計情報"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "平均トラフィック (通/分)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "送信メッセージ"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "受信メッセージ"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "バウンスメッセージ"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "拒否メッセージ"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "送信メッセージ"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "送信メッセージ"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "拒否メッセージ"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "平均トラフィックサイズ (バイト/分)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "受信サイズ"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "送信サイズ"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "メールトラフィック"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "グラフィカルな統計情報"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "ドメインを検索"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "適用"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "統計情報がありません"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "日"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "週"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "月"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "年"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "カスタム"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "不明なグラフィックセット"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "不明なグラフィックセット"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "カスタム期間が不正です"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr ""
|
||||
#~ "RRDtool を使用して、電子メールトラフィックに関するグラフィカルな統計情報を"
|
||||
#~ "表示します。"
|
||||
@@ -0,0 +1,24 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# cwatanab <chihiro.watanabe@live.jp>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2016-06-07 07:16+0000\n"
|
||||
"Last-Translator: cwatanab <chihiro.watanabe@live.jp>\n"
|
||||
"Language-Team: Japanese (Japan) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/ja_JP/)\n"
|
||||
"Language: ja_JP\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "ドメインを検索"
|
||||
@@ -0,0 +1,178 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Andrew <buddha@cryptolab.net>, 2014
|
||||
# TuxBrother <vrijwilligerswerk@wij.rs>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2014-12-31 11:37+0000\n"
|
||||
"Last-Translator: TuxBrother <vrijwilligerswerk@wij.rs>\n"
|
||||
"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/nl_NL/)\n"
|
||||
"Language: nl_NL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Algemeen"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Locatie van logbestand"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Locatie van logbestand gebruik om statistieken te maken"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Map om RRD bestanden op te slaan"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Locatie van map waar RRD bestanden staan"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "geweigerde berichten"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Statistieken"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Gemiddeld verkeer per minuut (berichten)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "verstuurde berichten"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "ontvangen berichten"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "geweigerde berichten"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "geweigerde berichten"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "verstuurde berichten"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "verstuurde berichten"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "geweigerde berichten"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Gemiddelde bandbreette per minuut (bytes)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "ontvangen grootte"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "verstuurde grootte"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Mailverkeer"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Grafische statistieken"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Zoek een domein"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Toepassen"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Geen statistieken beschikbaar"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Dag"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Week"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Maand"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Jaar"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Aangepast"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Onbekende grafische set"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Onbekende grafische set"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Ongeldige aangepaste periode"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Grafische statistieken over emailverkeer dmv. RRDtool"
|
||||
@@ -0,0 +1,25 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# TuxBrother <vrijwilligerswerk@wij.rs>, 2014
|
||||
# TuxBrother <vrijwilligerswerk@wij.rs>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2014-12-31 11:42+0000\n"
|
||||
"Last-Translator: TuxBrother <vrijwilligerswerk@wij.rs>\n"
|
||||
"Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/nl_NL/)\n"
|
||||
"Language: nl_NL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Zoek een domein"
|
||||
@@ -0,0 +1,172 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# sin88 <sin@sin.waw.pl>, 2016
|
||||
# Tomasz Proć <tomasz.proc@gmail.com>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2017-12-01 16:06+0000\n"
|
||||
"Last-Translator: Tomasz Proć <tomasz.proc@gmail.com>\n"
|
||||
"Language-Team: Polish (Poland) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/pl_PL/)\n"
|
||||
"Language: pl_PL\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n"
|
||||
"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n"
|
||||
"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Ogólne"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Ścieżka do pliku z logiem"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Sćieżka do pliku z logiem dla colect "
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Katalog do przechowywania plików RRD"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Katalog gdzie przechowywane są pliki RRD"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "Pokaż greylistowane wiadomości"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr "Rozróżniaj twarde i miękkie odrzuty (greylisting)"
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Statystyki"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr "Nie znaleziono binarki rrdtool."
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Średni ruch (wiadomości/minutę)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "Wysłane wiadomości"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "Odebrane wiadomości"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "Odbite wiadomości"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "Odrzucone wiadomości"
|
||||
|
||||
#: graphics.py:181
|
||||
msgid "virus messages"
|
||||
msgstr "wiadomości zawirusowane"
|
||||
|
||||
#: graphics.py:182
|
||||
msgid "spam messages"
|
||||
msgstr "wiadomości spam"
|
||||
|
||||
#: graphics.py:189
|
||||
msgid "greylisted messages"
|
||||
msgstr "wiadomości opóźnione (greylisting)"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Średnia normalna wielkość ruchu (bajtów/min)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "Ilość odebranych danych"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "Ilość wysłanych danych"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Ruch e-mail"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr "Średnia ilość tworzonych kont (konto/godzina)"
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr "Nowe konta"
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr "Konta"
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Graficzne statytyki"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Wyszukaj domenę"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Zastosuj"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Brak dostępnych statysty"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Dzień"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Tydzień"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Miesiąc"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Rok"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Własne"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Unknown graphic set"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Unknown graphic set"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Nieprawudłowy przedział czasowy"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Graficzne statystyki wiadomości z wykorzystaniem "
|
||||
@@ -0,0 +1,23 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# sin88 <sin@sin.waw.pl>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2017-09-22 09:57+0000\n"
|
||||
"Last-Translator: sin88 <sin@sin.waw.pl>\n"
|
||||
"Language-Team: Polish (Poland) (http://www.transifex.com/tonio/modoboa/language/pl_PL/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pl_PL\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Wyszukaj domenę"
|
||||
@@ -0,0 +1,179 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# csmk, 2014
|
||||
# Paulino Michelazzo <paulino@michelazzo.com.br>, 2014
|
||||
# Rafael Barretto Alves <ch3yd@hotmail.com>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2014-12-13 09:10+0000\n"
|
||||
"Last-Translator: Paulino Michelazzo <paulino@michelazzo.com.br>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/pt_BR/)\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Geral"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Caminho para o arquivo de log"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Caminho para o arquivo de log usado para coletar estatísticas"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Diretório para armazenar arquivos RRD"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Caminho para o diretório onde os arquivos RRD são armazenados"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "mensagens rejeitadas"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Estatísticas"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Tráfego médio (msgs/min)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "mensagens enviadas"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "mensagens recebidas"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "mensagens devolvidas"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "mensagens rejeitadas"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "mensagens enviadas"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "mensagens enviadas"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "mensagens rejeitadas"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Tamanho médio de tráfego (bytes/min)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "tamanho recebido"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "tamanho enviado"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Tráfego de e-mail"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Estatísticas gráficas"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Buscar um domínio"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Aplicar"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Não há estatísticas disponíveis"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Dia"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Semana"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Mês"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Ano"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Customizado"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Conjunto gráfico desconhecido"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Conjunto gráfico desconhecido"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Período customizado inválido"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Estatísticas gráficas sobre o tráfego de e-mails usando RRDtool"
|
||||
@@ -0,0 +1,24 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Paulino Michelazzo <paulino@michelazzo.com.br>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2014-12-13 09:14+0000\n"
|
||||
"Last-Translator: Paulino Michelazzo <paulino@michelazzo.com.br>\n"
|
||||
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/pt_BR/)\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Buscar um domínio"
|
||||
@@ -0,0 +1,182 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Damien Duponchelle <dduponchelle@gmail.com>, 2013
|
||||
# lusitan <lusitan@hushmail.com>, 2013
|
||||
# Mike C. <miguelmclara@gmail.com>, 2012
|
||||
# Mike C. <miguelmclara@gmail.com>, 2013-2014
|
||||
# Sandra Ribeiro <sandrarib@gmail.com>, 2012-2013
|
||||
# Sandra Ribeiro <sandrarib@gmail.com>, 2012
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2014-12-29 12:51+0000\n"
|
||||
"Last-Translator: Mike C. <miguelmclara@gmail.com>\n"
|
||||
"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/pt_PT/)\n"
|
||||
"Language: pt_PT\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Geral"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Caminho para o ficheiro log"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Caminho para o ficheiro de log usado para recolher as estatísticas"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Diretório para armazenar os ficheiros RRD"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Caminho para o diretório onde os ficheiros RRD são guardados"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "mensagens rejeitadas"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Estatísticas"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Trafego em média (msgs/min)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "mensagens enviadas"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "mensagens recebidas"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "mensagens devolvidas"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "mensagens rejeitadas"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "mensagens enviadas"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "mensagens enviadas"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "mensagens rejeitadas"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Tráfego em média normal por tamanho (bytes/min)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "tamanho recebido"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "tamanho enviado"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Tráfego de correio"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Estatísticas gráficas"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Procurar um domínio"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Aplicar"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Não há estatísticas disponíveis"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Dia"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Semana"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Mês"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Ano"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Personalizado"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Conjunto de gráficos desconhecido"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Conjunto de gráficos desconhecido"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Período personalizado inválido"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Estatísticas gráficas sobre tráfego de email usando RRDtool"
|
||||
@@ -0,0 +1,29 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# lusitan <lusitan@hushmail.com>, 2013
|
||||
# lusitan <lusitan@hushmail.com>, 2013
|
||||
# Mike C. <miguelmclara@gmail.com>, 2012
|
||||
# Mike C. <miguelmclara@gmail.com>, 2012
|
||||
# Mike C. <miguelmclara@gmail.com>, 2014
|
||||
# Sandra Ribeiro <sandrarib@gmail.com>, 2013
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2014-12-29 12:08+0000\n"
|
||||
"Last-Translator: Mike C. <miguelmclara@gmail.com>\n"
|
||||
"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/"
|
||||
"modoboa/language/pt_PT/)\n"
|
||||
"Language: pt_PT\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Pesquisar domínio"
|
||||
@@ -0,0 +1,170 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Andrei-Ilie Olteanu <andrei@flashsoft.ro>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2018-06-12 15:03+0000\n"
|
||||
"Last-Translator: Andrei-Ilie Olteanu <andrei@flashsoft.ro>\n"
|
||||
"Language-Team: Romanian (Romania) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/ro_RO/)\n"
|
||||
"Language: ro_RO\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?"
|
||||
"2:1));\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "General"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Calea către fișierul de log"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Calea către fișierul de log în care se colectează statistici"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Directorul în care se stochează fisierele RRD"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Calea către directorul în care se stochează fisierele RRD"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "Arată mesajele suspecte"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr "Diferențiază între mesjale rejectate hard și soft (suspecte)"
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Statistici"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr "Nu s-a gasit binarul rrdtool"
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Media traficului (mesaje/min)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "mesaje trimise"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "mesaje primite "
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "mesaje returnate"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "mesaje rejectate"
|
||||
|
||||
#: graphics.py:181
|
||||
msgid "virus messages"
|
||||
msgstr "mesaje cu virus"
|
||||
|
||||
#: graphics.py:182
|
||||
msgid "spam messages"
|
||||
msgstr "mesaje spam"
|
||||
|
||||
#: graphics.py:189
|
||||
msgid "greylisted messages"
|
||||
msgstr "mesaje suspecte"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Media de trafic (octecți/minut)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "mărime pentru primite"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "mărime pentru trimise"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Trafic Email"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr "Media creări de conturi (cont/oră)"
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr "Conturi noi"
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr "Conturi"
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Statistici grafice"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Cauta un domeniu"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Aplică"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Nu sunt disponibile statistici"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Zi"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Săptămană"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Lună"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "An"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Personalizat"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Set grafic necunoscut"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Set grafic necunoscut"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Perioada personalizată invalidă"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Statistici grafice despre traficul pe email folosind RRDtool"
|
||||
@@ -0,0 +1,23 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Andrei-Ilie Olteanu <andrei@flashsoft.ro>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2018-06-12 15:04+0000\n"
|
||||
"Last-Translator: Andrei-Ilie Olteanu <andrei@flashsoft.ro>\n"
|
||||
"Language-Team: Romanian (Romania) (http://www.transifex.com/tonio/modoboa/language/ro_RO/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ro_RO\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Cauta un domeniu"
|
||||
@@ -0,0 +1,179 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2013-12-03 09:35+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Russian (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"ru/)\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Основные"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Путь к лог файлу"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Путь к лог файлу для сбора статистики"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Папка для сохранения RRD файлов"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Путь к директории для сохранения RRD файлов"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "Отвергнутые сообщения"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Статистика"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
#, fuzzy
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Средний размер траффика"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "Отправлено сообщений"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "Принято сообщений"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "Возвращенные сообщения"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "Отвергнутые сообщения"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "Отправлено сообщений"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "Отправлено сообщений"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "Отвергнутые сообщения"
|
||||
|
||||
#: graphics.py:200
|
||||
#, fuzzy
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Средний размер траффика"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "Принято"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "Отправлено"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Почтовый траффик"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Графическая статистика"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Искать домен"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Применить"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Статистика не доступна"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "День"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Неделя"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Месяц"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "Год"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr ""
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Неизвестный графический набор "
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Неизвестный графический набор "
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Не верный выбор периода"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Графическая статистика о почтовом траффика использует RRDtool"
|
||||
@@ -0,0 +1,24 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2013-12-03 09:35+0000\n"
|
||||
"Last-Translator: Antoine Nguyen <tonio@ngyn.org>\n"
|
||||
"Language-Team: Russian (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"ru/)\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
|
||||
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Найти домен"
|
||||
@@ -0,0 +1,179 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Martin Persson <martin.jens.persson@gmail.com>, 2014
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2013
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2013,2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2015-01-13 15:18+0000\n"
|
||||
"Last-Translator: Olle Gustafsson <olle@dalnix.se>\n"
|
||||
"Language-Team: Swedish (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"sv/)\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "Generellt"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "Sökväg till loggfil"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "Sökväg till loggfil som används för att samla in statistik"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "Katalog för lagring av RRD filer"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "Sökväg till katalog där RRD filer lagras"
|
||||
|
||||
#: forms.py:38
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "avvisade meddelanden"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "Statistik"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "Genomsnittlig trafik (meddelanden/min)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "skickade meddelanden"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "mottagna meddelande"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "studsade meddelanden"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "avvisade meddelanden"
|
||||
|
||||
#: graphics.py:181
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "virus messages"
|
||||
msgstr "skickade meddelanden"
|
||||
|
||||
#: graphics.py:182
|
||||
#, fuzzy
|
||||
#| msgid "sent messages"
|
||||
msgid "spam messages"
|
||||
msgstr "skickade meddelanden"
|
||||
|
||||
#: graphics.py:189
|
||||
#, fuzzy
|
||||
#| msgid "rejected messages"
|
||||
msgid "greylisted messages"
|
||||
msgstr "avvisade meddelanden"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "Genomsnittlig normal trafik (bytes/min)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "mottagen storlek"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "sänd storlek"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "Mail trafik"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr ""
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "Grafisk statistik"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "Sök en domän"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "Applicera"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "Ingen statistik tillgänglig"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "Dag"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "Vecka"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "Månad"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "År"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "Anpassad"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "Okänt grafisk uppsättning"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "Okänt grafisk uppsättning"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "Ogiltig anpassad tid"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "Grafisk statistik om e-post trafik med hjälp av RRDtool"
|
||||
@@ -0,0 +1,25 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2013
|
||||
# Olle Gustafsson <olle@dalnix.se>, 2013,2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2015-01-13 15:21+0000\n"
|
||||
"Last-Translator: Olle Gustafsson <olle@dalnix.se>\n"
|
||||
"Language-Team: Swedish (http://www.transifex.com/projects/p/modoboa/language/"
|
||||
"sv/)\n"
|
||||
"Language: sv\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "Sök domän"
|
||||
@@ -0,0 +1,170 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# akong <akong@aspa.idv.tw>, 2018
|
||||
# Radium <ztl8702@126.com>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-17 11:24+0200\n"
|
||||
"PO-Revision-Date: 2018-06-28 09:01+0000\n"
|
||||
"Last-Translator: akong <akong@aspa.idv.tw>\n"
|
||||
"Language-Team: Chinese (Taiwan) (http://www.transifex.com/tonio/modoboa/"
|
||||
"language/zh_TW/)\n"
|
||||
"Language: zh_TW\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: forms.py:20
|
||||
msgid "General"
|
||||
msgstr "一般"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Path to the log file"
|
||||
msgstr "日誌檔的路徑"
|
||||
|
||||
#: forms.py:25
|
||||
msgid "Path to log file used to collect statistics"
|
||||
msgstr "日誌檔的路徑用於蒐集狀態"
|
||||
|
||||
#: forms.py:30
|
||||
msgid "Directory to store RRD files"
|
||||
msgstr "儲存 RRD 檔案的目錄"
|
||||
|
||||
#: forms.py:33
|
||||
msgid "Path to directory where RRD files are stored"
|
||||
msgstr "RRD 檔案已儲存到目錄路徑"
|
||||
|
||||
#: forms.py:38
|
||||
msgid "Show greylisted messages"
|
||||
msgstr "顯示灰名單郵件"
|
||||
|
||||
#: forms.py:41
|
||||
msgid "Differentiate between hard and soft rejects (greylisting)"
|
||||
msgstr "區分在硬的退件跟軟的退件之間 (灰名單)"
|
||||
|
||||
#: forms.py:59 handlers.py:22
|
||||
msgid "Statistics"
|
||||
msgstr "統計"
|
||||
|
||||
#: graphics.py:95
|
||||
msgid "Failed to locate rrdtool binary."
|
||||
msgstr "指定 rrdtools 位置失敗。"
|
||||
|
||||
#: graphics.py:174
|
||||
msgid "Average traffic (msgs/min)"
|
||||
msgstr "平均流量 (郵件數/分鐘)"
|
||||
|
||||
#: graphics.py:177
|
||||
msgid "sent messages"
|
||||
msgstr "已發訊息"
|
||||
|
||||
#: graphics.py:178
|
||||
msgid "received messages"
|
||||
msgstr "收到的訊息"
|
||||
|
||||
#: graphics.py:179
|
||||
msgid "bounced messages"
|
||||
msgstr "已退回郵件"
|
||||
|
||||
#: graphics.py:180
|
||||
msgid "rejected messages"
|
||||
msgstr "已拒絕郵件"
|
||||
|
||||
#: graphics.py:181
|
||||
msgid "virus messages"
|
||||
msgstr "病毒郵件"
|
||||
|
||||
#: graphics.py:182
|
||||
msgid "spam messages"
|
||||
msgstr "垃圾郵件"
|
||||
|
||||
#: graphics.py:189
|
||||
msgid "greylisted messages"
|
||||
msgstr "灰名單郵件"
|
||||
|
||||
#: graphics.py:200
|
||||
msgid "Average normal traffic size (bytes/min)"
|
||||
msgstr "平均流量大小 (位元組/分鐘)"
|
||||
|
||||
#: graphics.py:203
|
||||
msgid "received size"
|
||||
msgstr "已接收大小"
|
||||
|
||||
#: graphics.py:205
|
||||
msgid "sent size"
|
||||
msgstr "寄送大小"
|
||||
|
||||
#: graphics.py:213
|
||||
msgid "Mail traffic"
|
||||
msgstr "郵件流量"
|
||||
|
||||
#: graphics.py:258
|
||||
msgid "Average account creation (account/hour)"
|
||||
msgstr "建立帳號平均值 (帳號/小時)"
|
||||
|
||||
#: graphics.py:261
|
||||
msgid "New accounts"
|
||||
msgstr "新帳號"
|
||||
|
||||
#: graphics.py:268
|
||||
msgid "Accounts"
|
||||
msgstr "帳號"
|
||||
|
||||
#: templates/maillog/index.html:4
|
||||
msgid "Graphical statistics"
|
||||
msgstr "圖形狀態"
|
||||
|
||||
#: templates/maillog/index.html:44
|
||||
msgid "Search a domain"
|
||||
msgstr "搜尋網域"
|
||||
|
||||
#: templates/maillog/index.html:77
|
||||
msgid "Apply"
|
||||
msgstr "套用"
|
||||
|
||||
#: views.py:33
|
||||
msgid "No statistics available"
|
||||
msgstr "沒有可用的狀態"
|
||||
|
||||
#: views.py:40
|
||||
msgid "Day"
|
||||
msgstr "日"
|
||||
|
||||
#: views.py:41
|
||||
msgid "Week"
|
||||
msgstr "周"
|
||||
|
||||
#: views.py:42
|
||||
msgid "Month"
|
||||
msgstr "月"
|
||||
|
||||
#: views.py:43
|
||||
msgid "Year"
|
||||
msgstr "年"
|
||||
|
||||
#: views.py:44
|
||||
msgid "Custom"
|
||||
msgstr "自訂"
|
||||
|
||||
#: views.py:63
|
||||
msgid "Unknown graphic set"
|
||||
msgstr "未知圖形設定"
|
||||
|
||||
#: views.py:68
|
||||
#, fuzzy
|
||||
#| msgid "Unknown graphic set"
|
||||
msgid "Unknown domain"
|
||||
msgstr "未知圖形設定"
|
||||
|
||||
#: views.py:73
|
||||
msgid "Bad custom period"
|
||||
msgstr "錯誤的自訂期間"
|
||||
|
||||
#~ msgid "Graphical statistics about emails traffic using RRDtool"
|
||||
#~ msgstr "有關郵件流量的圖形狀態表是使用 RRDtool"
|
||||
@@ -0,0 +1,23 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# Translators:
|
||||
# Radium <ztl8702@126.com>, 2017
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Modoboa\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-03-03 09:37+0100\n"
|
||||
"PO-Revision-Date: 2017-09-23 14:31+0000\n"
|
||||
"Last-Translator: Radium <ztl8702@126.com>\n"
|
||||
"Language-Team: Chinese (Taiwan) (http://www.transifex.com/tonio/modoboa/language/zh_TW/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: zh_TW\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: static/modoboa_stats/js/stats.js:43
|
||||
msgid "Search a domain"
|
||||
msgstr "搜尋一個網域"
|
||||
@@ -0,0 +1,632 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""
|
||||
Postfix log parser.
|
||||
|
||||
This scripts parses a log file produced by postfix (or using the same
|
||||
format). It looks for predefined events and build statistics about
|
||||
their occurence rate.
|
||||
|
||||
At the, somes default graphics are generated using the grapher module.
|
||||
(see grapher.py)
|
||||
|
||||
Predefined events are:
|
||||
* Per domain sent/received messages,
|
||||
* Per domain received bad messages (bounced, reject for now),
|
||||
* Per domain sent/received traffics size,
|
||||
* Global consolidation of all previous events.
|
||||
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
|
||||
import rrdtool
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
|
||||
from modoboa.admin.models import Domain
|
||||
from modoboa.parameters import tools as param_tools
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
|
||||
from ... import lib
|
||||
from ... import models
|
||||
|
||||
|
||||
rrdstep = 60
|
||||
xpoints = 540
|
||||
points_per_sample = 3
|
||||
variables = ["sent", "recv", "bounced", "reject", "spam", "virus",
|
||||
"size_sent", "size_recv"]
|
||||
|
||||
|
||||
class LogParser:
|
||||
|
||||
def __init__(self, options, workdir, year=None, greylist=False):
|
||||
"""Constructor."""
|
||||
self.logfile = options["logfile"]
|
||||
self.debug = options["debug"]
|
||||
self.verbose = options["verbose"]
|
||||
try:
|
||||
self.f = io.open(self.logfile, encoding="utf-8")
|
||||
except IOError as errno:
|
||||
self._dprint("%s" % errno)
|
||||
sys.exit(1)
|
||||
self.workdir = workdir
|
||||
self.__year = year
|
||||
self.cfs = ["AVERAGE", "MAX"]
|
||||
|
||||
curtime = time.localtime()
|
||||
if not self.__year:
|
||||
self.__year = curtime.tm_year
|
||||
self.curmonth = curtime.tm_mon
|
||||
|
||||
self.data = {"global": {}}
|
||||
self.domains = []
|
||||
self._load_domain_list()
|
||||
|
||||
self.workdict = {}
|
||||
self.lupdates = {}
|
||||
|
||||
# set up regular expression
|
||||
self._date_expressions = [
|
||||
r"(?P<month>\w+)\s+(?P<day>\d+)\s+(?P<hour>\d+):(?P<min>\d+):(?P<sec>\d+)(?P<eol>.*)", # noqa
|
||||
r"(?P<year>\d+)-(?P<month>\d+)-(?P<day>\d+)T(?P<hour>\d+):(?P<min>\d+):(?P<sec>\d+)\.\d+\+\d+:\d+(?P<eol>.*)" # noqa
|
||||
]
|
||||
self._date_expressions = [
|
||||
re.compile(v) for v in self._date_expressions]
|
||||
self.date_expr = None
|
||||
self._regex = {
|
||||
"line": r"\s+([-\w\.]+)\s+(\w+)/?(\w*)[[](\d+)[]]:\s+(.*)",
|
||||
"id": r"(\w+): (.*)",
|
||||
"reject": r"reject: .*from=<.*>,? to=<[^@]+@([^>]+)>",
|
||||
"message-id": r"message-id=<([^>]*)>",
|
||||
"from+size": r"from=<([^>]*)>, size=(\d+)",
|
||||
"to+status": r"to=<([^>]*)>.*status=(\S+)",
|
||||
"orig_to": r"orig_to=<([^>]*)>.*",
|
||||
"amavis": r"(?P<result>INFECTED|SPAM|SPAMMY) .* <[^>]+> -> <[^@]+@(?P<domain>[^>]+)>.*", # noqa
|
||||
"rmilter_line": r"<(?P<hash>[0-9a-f]{10})>; (?P<line>.*)",
|
||||
"rmilter_msg_done": r"msg done: queue_id: <(?P<queue_id>[^>]+)>; message id: <(?P<message_id>[^>]+)>.*; from: <(?P<from>[^>]+)>; rcpt: <(?P<rcpt>[^>]+)>.*; spam scan: (?P<action>[^;]+); virus scan:", # noqa
|
||||
"rmilter_spam": r"mlfi_eom: (rejecting spam|add spam header to message according to spamd action)", # noqa
|
||||
"rmilter_virus": r"mlfi_eom:.* virus found",
|
||||
"rmilter_greylist": (
|
||||
r"GREYLIST\([0-9]+\.[0-9]{2}\)\[greylisted[^\]]*\]")
|
||||
}
|
||||
self._regex = {k: re.compile(v) for k, v in self._regex.items()}
|
||||
self._srs_regex = {
|
||||
"detect_srs": "^SRS[01][+-=]",
|
||||
"reverse_srs0": r"^SRS0[+-=]\S+=\S{2}=(\S+)=(\S+)\@\S+$",
|
||||
"reverse_srs1": r"^SRS1[+-=]\S+=\S+==\S+=\S{2}=(\S+)=(\S+)\@\S+$"
|
||||
}
|
||||
self._srs_regex = {
|
||||
k: re.compile(v, re.IGNORECASE) for k, v in self._srs_regex.items()
|
||||
}
|
||||
|
||||
self.greylist = greylist
|
||||
if greylist:
|
||||
variables.insert(4, "greylist")
|
||||
self._dprint("[settings] greylisting enabled")
|
||||
|
||||
self._prev_se = -1
|
||||
self._prev_mi = -1
|
||||
self._prev_ho = -1
|
||||
self.cur_t = 0
|
||||
|
||||
def _load_domain_list(self):
|
||||
"""Load the list of allowed domains."""
|
||||
for dom in Domain.objects.all():
|
||||
domname = str(dom.name)
|
||||
self.domains += [domname]
|
||||
self.data[domname] = {}
|
||||
|
||||
# Also add alias domains
|
||||
for alias in dom.domainalias_set.all():
|
||||
aliasname = str(alias.name)
|
||||
self.domains += [aliasname]
|
||||
self.data[aliasname] = {}
|
||||
|
||||
def _dprint(self, msg):
|
||||
"""Print a debug message if required.
|
||||
|
||||
:param str msg: debug message
|
||||
"""
|
||||
if not self.debug:
|
||||
return
|
||||
print(msg)
|
||||
|
||||
def _parse_date(self, line):
|
||||
"""Try to match a date inside :kw:`line` and to convert it to
|
||||
a timestamp.
|
||||
|
||||
We try different date format until we find valid one. We then
|
||||
store it for future use.
|
||||
|
||||
:param str line: a log entry
|
||||
:return: the remaining part of the line or None
|
||||
"""
|
||||
match = None
|
||||
if self.date_expr is None:
|
||||
for expr in self._date_expressions:
|
||||
match = expr.match(line)
|
||||
if match is not None:
|
||||
self.date_expr = expr
|
||||
break
|
||||
else:
|
||||
match = self.date_expr.match(line)
|
||||
if match is None:
|
||||
return None
|
||||
ho = match.group("hour")
|
||||
mi = match.group("min")
|
||||
se = match.group("sec")
|
||||
mo = match.group("month")
|
||||
da = match.group("day")
|
||||
try:
|
||||
ye = match.group("year")
|
||||
except IndexError:
|
||||
ye = self.year(mo)
|
||||
# Keep original timestamp
|
||||
self.orig_ts = lib.date_to_timestamp([ye, mo, da, ho, mi, se])
|
||||
|
||||
# Now get the current period (based on rrdstep)
|
||||
se = int(int(se) / rrdstep) # rrd step is one-minute => se = 0
|
||||
if self._prev_se != se or self._prev_mi != mi or self._prev_ho != ho:
|
||||
self.cur_t = lib.date_to_timestamp([ye, mo, da, ho, mi, se])
|
||||
self.cur_t = self.cur_t - self.cur_t % rrdstep
|
||||
self._prev_mi = mi
|
||||
self._prev_ho = ho
|
||||
self._prev_se = se
|
||||
return match.group("eol")
|
||||
|
||||
def init_rrd(self, fname, m):
|
||||
"""init_rrd.
|
||||
|
||||
Set-up Data Sources (DS)
|
||||
Set-up Round Robin Archives (RRA):
|
||||
- day,week,month and year archives
|
||||
- 2 types : AVERAGE and MAX
|
||||
|
||||
parameter : start time
|
||||
return : last epoch recorded
|
||||
"""
|
||||
ds_type = "ABSOLUTE"
|
||||
rows = xpoints / points_per_sample
|
||||
realrows = int(rows * 1.1) # ensure that the full range is covered
|
||||
day_steps = int(3600 * 24 / (rrdstep * rows))
|
||||
week_steps = day_steps * 7
|
||||
month_steps = week_steps * 5
|
||||
year_steps = month_steps * 12
|
||||
|
||||
# Set up data sources for our RRD
|
||||
params = []
|
||||
for v in variables:
|
||||
params += ["DS:%s:%s:%s:0:U" % (v, ds_type, rrdstep * 2)]
|
||||
|
||||
# Set up RRD to archive data
|
||||
for cf in ["AVERAGE", "MAX"]:
|
||||
for step in [day_steps, week_steps, month_steps, year_steps]:
|
||||
params += ["RRA:%s:0.5:%s:%s" % (cf, step, realrows)]
|
||||
|
||||
# With those setup, we can now created the RRD
|
||||
rrdtool.create(str(fname),
|
||||
"--start", str(m),
|
||||
"--step", str(rrdstep),
|
||||
*params)
|
||||
return m
|
||||
|
||||
def add_datasource_to_rrd(self, fname, dsname):
|
||||
"""Add a new data source to an exisitng file.
|
||||
|
||||
Add missing Data Sources (DS) to existing Round Robin Archive (RRA):
|
||||
See init_rrd for details.
|
||||
"""
|
||||
ds_def = "DS:%s:ABSOLUTE:%s:0:U" % (dsname, rrdstep * 2)
|
||||
rrdtool.tune(fname, ds_def)
|
||||
self._dprint("[rrd] added DS %s to %s" % (dsname, fname))
|
||||
|
||||
def add_point_to_rrd(self, fname, tpl, values, ts=None):
|
||||
"""Try to add a new point to RRD file."""
|
||||
if ts:
|
||||
values = "{}:{}".format(ts, values)
|
||||
if self.verbose:
|
||||
print("[rrd] VERBOSE update -t %s %s" % (tpl, values))
|
||||
try:
|
||||
rrdtool.update(str(fname), "-t", tpl, values)
|
||||
except rrdtool.OperationalError as e:
|
||||
op_match = re.match(r"unknown DS name '(\w+)'", str(e))
|
||||
if op_match is None:
|
||||
raise
|
||||
self.add_datasource_to_rrd(str(fname), op_match.group(1))
|
||||
rrdtool.update(str(fname), "-t", tpl, values)
|
||||
|
||||
def update_rrd(self, dom, t):
|
||||
"""update_rrd
|
||||
|
||||
Update RRD with records at t time.
|
||||
|
||||
True : if data are up-to-date for current minute
|
||||
False : syslog may have probably been already recorded
|
||||
or something wrong
|
||||
"""
|
||||
fname = "%s/%s.rrd" % (self.workdir, dom)
|
||||
m = t - (t % rrdstep)
|
||||
|
||||
self._dprint("[rrd] updating %s" % fname)
|
||||
if not os.path.exists(fname):
|
||||
self.lupdates[fname] = self.init_rrd(fname, m)
|
||||
self._dprint("[rrd] create new RRD file %s" % fname)
|
||||
else:
|
||||
if fname not in self.lupdates:
|
||||
self.lupdates[fname] = rrdtool.last(str(fname))
|
||||
|
||||
if m <= self.lupdates[fname]:
|
||||
if self.verbose:
|
||||
print("[rrd] VERBOSE events at %s already recorded in RRD" % m)
|
||||
return False
|
||||
|
||||
tpl = ""
|
||||
for v in variables:
|
||||
if tpl != "":
|
||||
tpl += ":"
|
||||
tpl += v
|
||||
# Missing some RRD steps
|
||||
# Est ce vraiment nécessaire... ?
|
||||
if m > self.lupdates[fname] + rrdstep:
|
||||
values = ""
|
||||
for v in variables:
|
||||
if values != "":
|
||||
values += ":"
|
||||
values += "0"
|
||||
for p in range(self.lupdates[fname] + rrdstep, m, rrdstep):
|
||||
self.add_point_to_rrd(fname, tpl, values, ts=p)
|
||||
|
||||
values = "%s" % m
|
||||
tpl = ""
|
||||
for v in variables:
|
||||
values += ":"
|
||||
values += str(self.data[dom][m][v])
|
||||
if tpl != "":
|
||||
tpl += ":"
|
||||
tpl += v
|
||||
self.add_point_to_rrd(fname, tpl, values)
|
||||
self.lupdates[fname] = m
|
||||
return True
|
||||
|
||||
def initcounters(self, dom):
|
||||
init = {}
|
||||
for v in variables:
|
||||
init[v] = 0
|
||||
self.data[dom][self.cur_t] = init
|
||||
|
||||
def inc_counter(self, dom, counter, val=1):
|
||||
if dom is not None and dom in self.domains:
|
||||
if self.cur_t not in self.data[dom]:
|
||||
self.initcounters(dom)
|
||||
self.data[dom][self.cur_t][counter] += val
|
||||
|
||||
if self.cur_t not in self.data["global"]:
|
||||
self.initcounters("global")
|
||||
self.data["global"][self.cur_t][counter] += val
|
||||
|
||||
def year(self, month):
|
||||
"""Return the appropriate year
|
||||
|
||||
Date used in log files don't always embark the year so we need
|
||||
to guess it :p
|
||||
|
||||
This method tries to deal with year changes in a simply
|
||||
(ugly?) way: if we currently are in january and the given
|
||||
month is different, return the current year -1. Otherwise,
|
||||
return the current year.
|
||||
|
||||
Obviously, this method only works for year to year + 1
|
||||
changes.
|
||||
|
||||
:param month: the month of the current record beeing parsed
|
||||
:return: an integer
|
||||
"""
|
||||
month = time.strptime(month, "%b").tm_mon if not month.isdigit() \
|
||||
else int(month)
|
||||
if self.curmonth == 1 and month != self.curmonth:
|
||||
return self.__year - 1
|
||||
return self.__year
|
||||
|
||||
def is_srs_forward(self, mail_address):
|
||||
""" Check if mail address has been mangled by SRS
|
||||
|
||||
Sender Rewriting Scheme (SRS) modifies mail adresses so that they
|
||||
always end in a local domain.
|
||||
|
||||
:param str mail_address
|
||||
:return a boolean
|
||||
"""
|
||||
return self._srs_regex["detect_srs"].match(mail_address) is not None
|
||||
|
||||
def reverse_srs(self, mail_address):
|
||||
""" Try to unwind a mail address rewritten by SRS
|
||||
|
||||
Sender Rewriting Scheme (SRS) modifies mail adresses so that they
|
||||
always end in a local domain. Common Postfix implementations of SRS
|
||||
rewrite all non-local mail addresss.
|
||||
|
||||
:param str mail_address
|
||||
:return a str
|
||||
"""
|
||||
m = self._srs_regex["reverse_srs0"].match(mail_address)
|
||||
m = self._srs_regex["reverse_srs1"].match(mail_address) \
|
||||
if m is None else m
|
||||
|
||||
if m is not None:
|
||||
return "%s@%s" % m.group(2, 1)
|
||||
else:
|
||||
return mail_address
|
||||
|
||||
def _parse_amavis(self, log, host, pid, subprog):
|
||||
""" Parse an Amavis log entry.
|
||||
|
||||
:param str log: logged message
|
||||
:param str host: hostname
|
||||
:param str pid: process ID
|
||||
:return: True on success
|
||||
"""
|
||||
m = self._regex["amavis"].search(log)
|
||||
if m is not None:
|
||||
dom = m.group("domain")
|
||||
spam_result = m.group("result")
|
||||
if dom is not None and dom in self.domains:
|
||||
if spam_result == "INFECTED":
|
||||
self.inc_counter(dom, "virus")
|
||||
elif spam_result in ["SPAM", "SPAMMY"]:
|
||||
self.inc_counter(dom, "spam")
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _parse_rmilter(self, log, host, pid, subprog):
|
||||
""" Parse an Rmilter log entry.
|
||||
|
||||
:param str log: logged message
|
||||
:param str host: hostname
|
||||
:param str pid: process ID
|
||||
:return: True on success
|
||||
"""
|
||||
m = self._regex["rmilter_line"].match(log)
|
||||
if m is None:
|
||||
return False
|
||||
rmilter_hash, msg = m.groups()
|
||||
workdict_key = "rmilter_" + rmilter_hash
|
||||
|
||||
# Virus check must come before spam check due to pattern similarity.
|
||||
m = self._regex["rmilter_virus"].match(msg)
|
||||
if m is not None:
|
||||
self.workdict[workdict_key] = {
|
||||
"action": "virus"
|
||||
}
|
||||
return True
|
||||
m = self._regex["rmilter_spam"].match(msg)
|
||||
if m is not None:
|
||||
self.workdict[workdict_key] = {
|
||||
"action": "spam"
|
||||
}
|
||||
return True
|
||||
|
||||
# Greylisting
|
||||
if self.greylist:
|
||||
m = self._regex["rmilter_greylist"].search(msg)
|
||||
if m is not None:
|
||||
self.workdict[workdict_key] = {
|
||||
"action": "greylist"
|
||||
}
|
||||
return True
|
||||
|
||||
# Gather information about message sender and queue ID
|
||||
m = self._regex["rmilter_msg_done"].match(msg)
|
||||
if m is not None:
|
||||
dom = split_mailbox(m.group("rcpt"))[1]
|
||||
|
||||
if workdict_key in self.workdict:
|
||||
action = self.workdict[workdict_key].get("action", None)
|
||||
if action is not None:
|
||||
self.inc_counter(dom, action)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _parse_postfix(self, log, host, pid, subprog):
|
||||
""" Parse a log entry generated by Postfix.
|
||||
|
||||
:param str log: logged message
|
||||
:param str host: hostname
|
||||
:param str pid: process ID
|
||||
:return: True on success
|
||||
"""
|
||||
m = self._regex["id"].match(log)
|
||||
if m is None:
|
||||
return False
|
||||
|
||||
queue_id, msg = m.groups()
|
||||
|
||||
# Handle rejected mails.
|
||||
if queue_id == "NOQUEUE":
|
||||
m = self._regex["reject"].match(msg)
|
||||
dom = m.group(1) if m is not None else None
|
||||
if dom in self.domains:
|
||||
condition = (
|
||||
self.greylist and (
|
||||
"Greylisted" in msg or
|
||||
(subprog == "postscreen" and " 450 " in msg))
|
||||
)
|
||||
if condition:
|
||||
self.inc_counter(dom, "greylist")
|
||||
else:
|
||||
self.inc_counter(dom, "reject")
|
||||
return True
|
||||
|
||||
# Message acknowledged.
|
||||
m = self._regex["message-id"].search(msg)
|
||||
if m is not None:
|
||||
self.workdict[queue_id] = {"from": m.group(1), "size": 0}
|
||||
return True
|
||||
|
||||
# Message enqueued.
|
||||
m = self._regex["from+size"].search(msg)
|
||||
if m is not None:
|
||||
self.workdict[queue_id] = {
|
||||
"from": self.reverse_srs(m.group(1)),
|
||||
"size": int(m.group(2))
|
||||
}
|
||||
return True
|
||||
|
||||
# Message disposition.
|
||||
m = self._regex["to+status"].search(msg)
|
||||
if m is None:
|
||||
return False
|
||||
(msg_to, msg_status) = m.groups()
|
||||
if queue_id not in self.workdict:
|
||||
self._dprint("[parser] inconsistent mail (%s: %s), skipping"
|
||||
% (queue_id, msg_to))
|
||||
return True
|
||||
if msg_status not in variables:
|
||||
self._dprint("[parser] unsupported status %s, skipping"
|
||||
% msg_status)
|
||||
return True
|
||||
|
||||
# orig_to is optional.
|
||||
m = self._regex["orig_to"].search(msg)
|
||||
msg_orig_to = m.group(1) if m is not None else None
|
||||
|
||||
# Handle local "from" domains.
|
||||
from_domain = split_mailbox(self.workdict[queue_id]["from"])[1]
|
||||
if from_domain is not None and from_domain in self.domains:
|
||||
self.inc_counter(from_domain, "sent")
|
||||
self.inc_counter(from_domain, "size_sent",
|
||||
self.workdict[queue_id]["size"])
|
||||
|
||||
# Handle local "to" domains.
|
||||
to_domain = None
|
||||
condition = (
|
||||
msg_orig_to is not None and
|
||||
not self.is_srs_forward(msg_orig_to)
|
||||
)
|
||||
if condition:
|
||||
to_domain = split_mailbox(msg_orig_to)[1]
|
||||
if to_domain is None:
|
||||
to_domain = split_mailbox(msg_to)[1]
|
||||
|
||||
if msg_status == "sent":
|
||||
self.inc_counter(to_domain, "recv")
|
||||
self.inc_counter(to_domain, "size_recv",
|
||||
self.workdict[queue_id]["size"])
|
||||
else:
|
||||
self.inc_counter(to_domain, msg_status)
|
||||
|
||||
last_message = models.Maillog.objects.last()
|
||||
cur_dt = datetime.fromtimestamp(self.orig_ts)
|
||||
tz = timezone.get_current_timezone()
|
||||
cur_dt = tz.localize(cur_dt)
|
||||
condition = (
|
||||
last_message and (
|
||||
cur_dt < last_message.date or
|
||||
(cur_dt == last_message.date and
|
||||
models.Maillog.objects.filter(
|
||||
date=cur_dt, queue_id=queue_id).exists())
|
||||
)
|
||||
)
|
||||
if not condition:
|
||||
if from_domain in self.domains:
|
||||
from_domain = Domain.objects.filter(
|
||||
Q(name=from_domain) |
|
||||
Q(domainalias__name=from_domain)
|
||||
).first()
|
||||
else:
|
||||
from_domain = None
|
||||
if to_domain in self.domains:
|
||||
to_domain = Domain.objects.filter(
|
||||
Q(name=to_domain) |
|
||||
Q(domainalias__name=to_domain)
|
||||
).first()
|
||||
else:
|
||||
to_domain = None
|
||||
if msg_status == "sent" and to_domain:
|
||||
msg_status = "received"
|
||||
models.Maillog.objects.create(
|
||||
queue_id=queue_id,
|
||||
date=cur_dt,
|
||||
sender=self.workdict[queue_id]["from"],
|
||||
rcpt=msg_to,
|
||||
original_rcpt=msg_orig_to,
|
||||
size=self.workdict[queue_id]["size"],
|
||||
status=msg_status,
|
||||
from_domain=from_domain,
|
||||
to_domain=to_domain
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
def _parse_line(self, line):
|
||||
"""Parse a single log line.
|
||||
|
||||
:param str line: log line
|
||||
"""
|
||||
line = self._parse_date(line)
|
||||
if line is None:
|
||||
return
|
||||
m = self._regex["line"].match(line)
|
||||
if not m:
|
||||
return
|
||||
host, prog, subprog, pid, log = m.groups()
|
||||
|
||||
try:
|
||||
parser = getattr(self, "_parse_{}".format(prog))
|
||||
if not parser(log, host, pid, subprog):
|
||||
self._dprint("[parser] ignoring %r log: %r" % (prog, log))
|
||||
except AttributeError:
|
||||
self._dprint(
|
||||
"[parser] no log handler for \"{}\": {}".format(prog, log))
|
||||
|
||||
def process(self):
|
||||
"""Process the log file.
|
||||
|
||||
We parse it and then generate standard graphics (day, week,
|
||||
month).
|
||||
"""
|
||||
for line in self.f.readlines():
|
||||
self._parse_line(line)
|
||||
|
||||
for dom, data in self.data.items():
|
||||
self._dprint("[rrd] dealing with domain %s" % dom)
|
||||
for t in sorted(data.keys()):
|
||||
self.update_rrd(dom, t)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Log file parser"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
"""Add extra arguments to command line."""
|
||||
parser.add_argument(
|
||||
"--logfile", default=None,
|
||||
help="postfix log in syslog format", metavar="FILE")
|
||||
parser.add_argument(
|
||||
"--verbose", default=False, action="store_true",
|
||||
dest="verbose", help="Set verbose mode")
|
||||
parser.add_argument(
|
||||
"--debug", default=False, action="store_true",
|
||||
help="Set debug mode")
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if options["logfile"] is None:
|
||||
options["logfile"] = param_tools.get_global_parameter(
|
||||
"logfile", app="maillog")
|
||||
greylist = param_tools.get_global_parameter(
|
||||
"greylist", raise_exception=False)
|
||||
p = LogParser(
|
||||
options, param_tools.get_global_parameter("rrd_rootdir"),
|
||||
None, greylist
|
||||
)
|
||||
p.process()
|
||||
@@ -0,0 +1,84 @@
|
||||
"""Management command to update various statistics."""
|
||||
|
||||
import os
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import rrdtool
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils import timezone
|
||||
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.parameters import tools as param_tools
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
"""Update statistics."""
|
||||
|
||||
help = "Update modoboa statistics"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
"""Add extra arguments to command line."""
|
||||
parser.add_argument(
|
||||
"--rebuild", action="store_true",
|
||||
help="Rebuild statistics from the begining")
|
||||
|
||||
def _create_new_accounts_rrd_file(self, fname, start):
|
||||
"""Create RRD file."""
|
||||
step = 3600
|
||||
ds_name = "new_accounts"
|
||||
params = ["DS:{}:ABSOLUTE:{}:0:U".format(ds_name, step * 2)]
|
||||
params += [
|
||||
"RRA:AVERAGE:0.5:1:48", # 48 hours with a 1h granularity
|
||||
"RRA:AVERAGE:0.5:24:31", # 31 days with a 1d granularity
|
||||
"RRA:AVERAGE:0.5:168:52", # 52 weeks with a 1w granularity
|
||||
"RRA:AVERAGE:0.5:5208:24", # 24 months with a 1m granularity
|
||||
]
|
||||
rrdtool.create(
|
||||
str(fname), "--start", str(start), "--step", str(step),
|
||||
*params
|
||||
)
|
||||
|
||||
def update_account_creation_stats(self, rebuild=False):
|
||||
"""Look for newly created accounts."""
|
||||
db_path = os.path.join(self.rootdir, "new_accounts.rrd")
|
||||
data = []
|
||||
if not rebuild:
|
||||
end = timezone.now().replace(minute=0, second=0, microsecond=0)
|
||||
start = end - relativedelta(hours=1)
|
||||
new_accounts = core_models.User.objects.filter(
|
||||
date_joined__gte=start, date_joined__lt=end).count()
|
||||
data.append(
|
||||
"{}:{}".format(int(end.strftime("%s")), new_accounts * 60))
|
||||
else:
|
||||
existing_stats = {}
|
||||
start = None
|
||||
for user in core_models.User.objects.all().order_by("date_joined"):
|
||||
hour = user.date_joined.replace(
|
||||
minute=0, second=0, microsecond=0) + relativedelta(hours=1)
|
||||
if start is None:
|
||||
start = hour
|
||||
hour = int(hour.strftime("%s"))
|
||||
if hour not in existing_stats:
|
||||
existing_stats[hour] = 0
|
||||
existing_stats[hour] += 1
|
||||
end = timezone.now().replace(
|
||||
minute=0, second=0, microsecond=0) + relativedelta(hours=1)
|
||||
if os.path.exists(db_path):
|
||||
os.unlink(db_path)
|
||||
hour = start
|
||||
while hour <= end:
|
||||
new_accounts = existing_stats.get(int(hour.strftime("%s")), 0)
|
||||
data.append("{}:{}".format(
|
||||
int(hour.strftime("%s")), new_accounts * 60))
|
||||
hour += relativedelta(hours=1)
|
||||
if not os.path.exists(db_path):
|
||||
self._create_new_accounts_rrd_file(
|
||||
db_path, int((start - relativedelta(hours=1)).strftime("%s"))
|
||||
)
|
||||
rrdtool.update(str(db_path), *data)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
"""Entry point."""
|
||||
self.rootdir = param_tools.get_global_parameter("rrd_rootdir")
|
||||
self.update_account_creation_stats(options["rebuild"])
|
||||
@@ -0,0 +1,34 @@
|
||||
# Generated by Django 2.2.12 on 2020-09-16 09:13
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('admin', '0017_alarm'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Maillog',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('queue_id', models.CharField(max_length=50)),
|
||||
('date', models.DateTimeField()),
|
||||
('sender', models.EmailField(max_length=254)),
|
||||
('rcpt', models.EmailField(max_length=254)),
|
||||
('original_rcpt', models.EmailField(max_length=254, null=True)),
|
||||
('size', models.PositiveIntegerField()),
|
||||
('status', models.CharField(max_length=15)),
|
||||
('from_domain', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sent_messages_log', to='admin.Domain')),
|
||||
('to_domain', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='recv_messages_log', to='admin.Domain')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['date'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,36 @@
|
||||
# Generated by Django 2.2.12 on 2020-09-16 11:46
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def rename_settings(apps, schema_editor):
|
||||
LocalConfig = apps.get_model("core", "LocalConfig")
|
||||
lc = LocalConfig.objects.first()
|
||||
if not lc:
|
||||
return
|
||||
stats_params = lc._parameters.pop("modoboa_stats", None)
|
||||
if stats_params:
|
||||
lc._parameters["maillog"] = stats_params
|
||||
lc.save()
|
||||
|
||||
|
||||
def backwards(apps, schema_editor):
|
||||
LocalConfig = apps.get_model("core", "LocalConfig")
|
||||
lc = LocalConfig.objects.first()
|
||||
if not lc:
|
||||
return
|
||||
params = lc._parameters.pop("maillog", None)
|
||||
if params:
|
||||
lc._parameters["modoboa_stats"] = params
|
||||
lc.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('maillog', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(rename_settings, backwards),
|
||||
]
|
||||
@@ -0,0 +1,27 @@
|
||||
"""App. related models."""
|
||||
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Maillog(models.Model):
|
||||
"""A model to store message logs."""
|
||||
|
||||
queue_id = models.CharField(max_length=50)
|
||||
date = models.DateTimeField()
|
||||
sender = models.EmailField()
|
||||
rcpt = models.EmailField()
|
||||
original_rcpt = models.EmailField(null=True)
|
||||
size = models.PositiveIntegerField()
|
||||
status = models.CharField(max_length=15)
|
||||
|
||||
from_domain = models.ForeignKey(
|
||||
"admin.Domain", on_delete=models.SET_NULL, null=True,
|
||||
related_name="sent_messages_log"
|
||||
)
|
||||
to_domain = models.ForeignKey(
|
||||
"admin.Domain", on_delete=models.SET_NULL, null=True,
|
||||
related_name="recv_messages_log"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ['date']
|
||||
@@ -0,0 +1,301 @@
|
||||
"""Parsing tools for maillog related files."""
|
||||
|
||||
import io
|
||||
import re
|
||||
import time
|
||||
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.lib.email_utils import split_mailbox
|
||||
|
||||
from . import utils
|
||||
|
||||
|
||||
class MaillogParser:
|
||||
"""Main parser class for maillog file."""
|
||||
|
||||
def __init__(self, year=None, greylist=False, verbose=False, debug=False):
|
||||
"""Constructor."""
|
||||
self.debug = debug
|
||||
self.verbose = verbose
|
||||
|
||||
self.domains = []
|
||||
self._load_domain_list()
|
||||
|
||||
self.workdict = {}
|
||||
self.lupdates = {}
|
||||
|
||||
self.__year = year
|
||||
curtime = time.localtime()
|
||||
if not self.__year:
|
||||
self.__year = curtime.tm_year
|
||||
self.curmonth = curtime.tm_mon
|
||||
|
||||
# set up regular expression
|
||||
self._date_expressions = [
|
||||
r"(?P<month>\w+)\s+(?P<day>\d+)\s+(?P<hour>\d+):(?P<min>\d+):(?P<sec>\d+)(?P<eol>.*)", # noqa
|
||||
r"(?P<year>\d+)-(?P<month>\d+)-(?P<day>\d+)T(?P<hour>\d+):(?P<min>\d+):(?P<sec>\d+)\.\d+\+\d+:\d+(?P<eol>.*)" # noqa
|
||||
]
|
||||
self._date_expressions = [
|
||||
re.compile(v) for v in self._date_expressions]
|
||||
self.date_expr = None
|
||||
self._regex = {
|
||||
"line": r"\s+([-\w\.]+)\s+(\w+)/?(\w*)[[](\d+)[]]:\s+(.*)",
|
||||
"id": r"(\w+): (.*)",
|
||||
"reject": r"reject: .*from=<.*>,? to=<[^@]+@([^>]+)>",
|
||||
"message-id": r"message-id=<([^>]*)>",
|
||||
"from+size": r"from=<([^>]*)>, size=(\d+)",
|
||||
"to+status": r"to=<([^>]*)>.*status=(\S+)",
|
||||
"orig_to": r"orig_to=<([^>]*)>.*",
|
||||
}
|
||||
self._regex = {k: re.compile(v) for k, v in self._regex.items()}
|
||||
self._srs_regex = {
|
||||
"detect_srs": "^SRS[01][+-=]",
|
||||
"reverse_srs0": r"^SRS0[+-=]\S+=\S{2}=(\S+)=(\S+)\@\S+$",
|
||||
"reverse_srs1": r"^SRS1[+-=]\S+=\S+==\S+=\S{2}=(\S+)=(\S+)\@\S+$"
|
||||
}
|
||||
self._srs_regex = {
|
||||
k: re.compile(v, re.IGNORECASE) for k, v in self._srs_regex.items()
|
||||
}
|
||||
|
||||
self.greylist = greylist
|
||||
if greylist:
|
||||
self._dprint("[settings] greylisting enabled")
|
||||
|
||||
def _load_domain_list(self):
|
||||
"""Load the list of allowed domains."""
|
||||
for dom in admin_models.Domain.objects.all():
|
||||
domname = str(dom.name)
|
||||
self.domains += [domname]
|
||||
# Also add alias domains
|
||||
for alias in dom.domainalias_set.all():
|
||||
aliasname = str(alias.name)
|
||||
self.domains += [aliasname]
|
||||
|
||||
def _dprint(self, msg):
|
||||
"""Print a debug message if required.
|
||||
|
||||
:param str msg: debug message
|
||||
"""
|
||||
if not self.debug:
|
||||
return
|
||||
print(msg)
|
||||
|
||||
def year(self, month):
|
||||
"""Return the appropriate year
|
||||
|
||||
Date used in log files don't always embark the year so we need
|
||||
to guess it :p
|
||||
|
||||
This method tries to deal with year changes in a simply
|
||||
(ugly?) way: if we currently are in january and the given
|
||||
month is different, return the current year -1. Otherwise,
|
||||
return the current year.
|
||||
|
||||
Obviously, this method only works for year to year + 1
|
||||
changes.
|
||||
|
||||
:param month: the month of the current record beeing parsed
|
||||
:return: an integer
|
||||
"""
|
||||
month = (
|
||||
time.strptime(month, "%b").tm_mon if not month.isdigit()
|
||||
else int(month)
|
||||
)
|
||||
if self.curmonth == 1 and month != self.curmonth:
|
||||
return self.__year - 1
|
||||
return self.__year
|
||||
|
||||
def _store_current_date(self, match):
|
||||
"""Transform and store parsed date."""
|
||||
ho = match.group("hour")
|
||||
mi = match.group("min")
|
||||
se = match.group("sec")
|
||||
mo = match.group("month")
|
||||
da = match.group("day")
|
||||
try:
|
||||
ye = match.group("year")
|
||||
except IndexError:
|
||||
ye = self.year(mo)
|
||||
self.cur_t = utils.date_to_timestamp([ye, mo, da, ho, mi, se])
|
||||
|
||||
def _parse_date(self, line):
|
||||
"""Try to match a date inside :kw:`line` and to convert it to
|
||||
a timestamp.
|
||||
|
||||
We try different date format until we find valid one. We then
|
||||
store it for future use.
|
||||
|
||||
:param str line: a log entry
|
||||
:return: the remaining part of the line or None
|
||||
"""
|
||||
match = None
|
||||
if self.date_expr is None:
|
||||
for expr in self._date_expressions:
|
||||
match = expr.match(line)
|
||||
if match is not None:
|
||||
self.date_expr = expr
|
||||
break
|
||||
else:
|
||||
match = self.date_expr.match(line)
|
||||
if match is None:
|
||||
return None
|
||||
self._store_current_date(match)
|
||||
return match.group("eol")
|
||||
|
||||
def is_srs_forward(self, mail_address):
|
||||
""" Check if mail address has been mangled by SRS
|
||||
|
||||
Sender Rewriting Scheme (SRS) modifies mail adresses so that they
|
||||
always end in a local domain.
|
||||
|
||||
:param str mail_address
|
||||
:return a boolean
|
||||
"""
|
||||
return self._srs_regex["detect_srs"].match(mail_address) is not None
|
||||
|
||||
def reverse_srs(self, mail_address):
|
||||
""" Try to unwind a mail address rewritten by SRS
|
||||
|
||||
Sender Rewriting Scheme (SRS) modifies mail adresses so that they
|
||||
always end in a local domain. Common Postfix implementations of SRS
|
||||
rewrite all non-local mail addresss.
|
||||
|
||||
:param str mail_address
|
||||
:return a str
|
||||
"""
|
||||
m = self._srs_regex["reverse_srs0"].match(mail_address)
|
||||
m = self._srs_regex["reverse_srs1"].match(mail_address) \
|
||||
if m is None else m
|
||||
|
||||
if m is not None:
|
||||
return "%s@%s" % m.group(2, 1)
|
||||
return mail_address
|
||||
|
||||
def new_domain_event(self, domain, name, size=None):
|
||||
"""Take action about new event for domain."""
|
||||
pass
|
||||
|
||||
def new_message_processed(
|
||||
self, queue_id, msg_status, from_domain, to_domain, msg_to,
|
||||
msg_orig_to):
|
||||
"""Store new message in local database."""
|
||||
pass
|
||||
|
||||
def _parse_postfix(self, log, host, pid, subprog):
|
||||
""" Parse a log entry generated by Postfix.
|
||||
|
||||
:param str log: logged message
|
||||
:param str host: hostname
|
||||
:param str pid: process ID
|
||||
:return: True on success
|
||||
"""
|
||||
m = self._regex["id"].match(log)
|
||||
if m is None:
|
||||
return False
|
||||
|
||||
queue_id, msg = m.groups()
|
||||
|
||||
# Handle rejected mails.
|
||||
if queue_id == "NOQUEUE":
|
||||
m = self._regex["reject"].match(msg)
|
||||
dom = m.group(1) if m is not None else None
|
||||
if dom in self.domains:
|
||||
condition = (
|
||||
self.greylist and (
|
||||
"Greylisted" in msg or
|
||||
(subprog == "postscreen" and " 450 " in msg))
|
||||
)
|
||||
self.new_domain_event(
|
||||
dom, "greylist" if condition else "reject")
|
||||
return True
|
||||
|
||||
# Message acknowledged.
|
||||
m = self._regex["message-id"].search(msg)
|
||||
if m is not None:
|
||||
self.workdict[queue_id] = {"from": m.group(1), "size": 0}
|
||||
return True
|
||||
|
||||
# Message enqueued.
|
||||
m = self._regex["from+size"].search(msg)
|
||||
if m is not None:
|
||||
self.workdict[queue_id] = {
|
||||
"from": self.reverse_srs(m.group(1)),
|
||||
"size": int(m.group(2))
|
||||
}
|
||||
return True
|
||||
|
||||
# Message disposition.
|
||||
m = self._regex["to+status"].search(msg)
|
||||
if m is None:
|
||||
return False
|
||||
(msg_to, msg_status) = m.groups()
|
||||
if queue_id not in self.workdict:
|
||||
self._dprint("[parser] inconsistent mail (%s: %s), skipping"
|
||||
% (queue_id, msg_to))
|
||||
return True
|
||||
|
||||
# orig_to is optional.
|
||||
m = self._regex["orig_to"].search(msg)
|
||||
msg_orig_to = m.group(1) if m is not None else None
|
||||
|
||||
# Handle local "from" domains.
|
||||
from_domain = split_mailbox(self.workdict[queue_id]["from"])[1]
|
||||
if from_domain is not None and from_domain in self.domains:
|
||||
self.new_domain_event(
|
||||
from_domain, "sent", self.workdict[queue_id]["size"])
|
||||
|
||||
# Handle local "to" domains.
|
||||
to_domain = None
|
||||
condition = (
|
||||
msg_orig_to is not None and
|
||||
not self.is_srs_forward(msg_orig_to)
|
||||
)
|
||||
if condition:
|
||||
to_domain = split_mailbox(msg_orig_to)[1]
|
||||
if to_domain is None:
|
||||
to_domain = split_mailbox(msg_to)[1]
|
||||
|
||||
if msg_status == "sent":
|
||||
msg_status = "recv"
|
||||
self.new_domain_event(
|
||||
to_domain, "recv", self.workdict[queue_id]["size"])
|
||||
|
||||
# Store log entry
|
||||
self.new_message_processed(
|
||||
queue_id, msg_status, from_domain, to_domain, msg_to, msg_orig_to)
|
||||
|
||||
return True
|
||||
|
||||
def _parse_line(self, line):
|
||||
"""Parse a single log line.
|
||||
|
||||
:param str line: log line
|
||||
"""
|
||||
line = self._parse_date(line)
|
||||
if line is None:
|
||||
return
|
||||
m = self._regex["line"].match(line)
|
||||
if not m:
|
||||
return
|
||||
host, prog, subprog, pid, log = m.groups()
|
||||
|
||||
try:
|
||||
parser = getattr(self, "_parse_{}".format(prog))
|
||||
if not parser(log, host, pid, subprog):
|
||||
self._dprint("[parser] ignoring %r log: %r" % (prog, log))
|
||||
except AttributeError:
|
||||
self._dprint(
|
||||
"[parser] no log handler for \"%r\": %r".format(prog, log))
|
||||
|
||||
def parse(self, logfile):
|
||||
"""Process the log file."""
|
||||
try:
|
||||
fp = io.open(logfile, encoding="utf-8")
|
||||
except IOError as errno:
|
||||
self._dprint("%s" % errno)
|
||||
return
|
||||
|
||||
for line in fp.readlines():
|
||||
self._parse_line(line)
|
||||
|
||||
fp.close()
|
||||
@@ -0,0 +1,5 @@
|
||||
"""Modoboa stats signals."""
|
||||
|
||||
import django.dispatch
|
||||
|
||||
get_graph_sets = django.dispatch.Signal(providing_args=["user"])
|
||||
@@ -0,0 +1,71 @@
|
||||
#menubar {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.chart {
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.grid .tick {
|
||||
stroke: darkgrey;
|
||||
stroke-dasharray: 1, 2;
|
||||
opacity: 0.9;
|
||||
}
|
||||
.grid path {
|
||||
stroke-width: 0;
|
||||
}
|
||||
|
||||
.line_over {
|
||||
stroke: darkgrey;
|
||||
stroke-width: 1.5px;
|
||||
stroke-dasharray: 1, 2;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.axis {
|
||||
font-size: 0.7em;
|
||||
}
|
||||
|
||||
.axis path,
|
||||
.axis line {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.area, .area2 {
|
||||
fill-opacity: .6;
|
||||
}
|
||||
|
||||
.brush .extent {
|
||||
stroke: #fff;
|
||||
fill-opacity: .125;
|
||||
shape-rendering: crispEdges;
|
||||
}
|
||||
|
||||
.legend rect {
|
||||
fill: none;
|
||||
stroke: black;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.tip {
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
top: 60px;
|
||||
display: none;
|
||||
font-size: 0.9em;
|
||||
padding: 5px;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.tip p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tracker {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// d3.legend.js
|
||||
// (C) 2012 ziggy.jonsson.nyc@gmail.com
|
||||
// MIT licence
|
||||
|
||||
(function() {
|
||||
d3.legend = function(g, clicked) {
|
||||
g.each(function() {
|
||||
var g = d3.select(this),
|
||||
items = {},
|
||||
svg = d3.select(g.property("nearestViewportElement")),
|
||||
legendPadding = g.attr("data-style-padding") || 5,
|
||||
lb = g.selectAll(".legend-box").data([true]),
|
||||
li = g.selectAll(".legend-items").data([true]);
|
||||
|
||||
lb.enter().append("rect").classed("legend-box", true);
|
||||
li.enter().append("g").classed("legend-items", true);
|
||||
|
||||
svg.selectAll("[data-legend]").each(function() {
|
||||
var self = d3.select(this);
|
||||
|
||||
items[self.attr("data-legend")] = {
|
||||
pos: self.attr("data-legend-pos") || this.getBBox().y,
|
||||
color: self.attr("data-legend-color") != undefined ? self.attr("data-legend-color") : self.style("fill") != 'none' ? self.style("fill") : self.style("stroke")
|
||||
};
|
||||
});
|
||||
|
||||
items = d3.entries(items).sort(function(a, b) {
|
||||
return a.value.pos - b.value.pos;
|
||||
});
|
||||
|
||||
li.selectAll("text")
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("text"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("y", function(d, i) { return i + "em"; })
|
||||
.attr("x", "1em")
|
||||
.text(function(d) { return d.key; });
|
||||
|
||||
li.selectAll("circle")
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("circle"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("cy", function(d, i) { return i - 0.25 + "em"; })
|
||||
.attr("cx", 0)
|
||||
.attr("r", "4px")
|
||||
.style("stroke", function(d) { return d.value.color; })
|
||||
.style("stroke-width", "1px")
|
||||
.style("stroke-opacity", 0.8)
|
||||
.style("fill", function(d) { return d.value.color; })
|
||||
.on("click", function(d) {
|
||||
var curve = d3.selectAll("[data-legend='" + d.key + "']");
|
||||
var state = (curve.style("display") == "none")
|
||||
? "block" : "none";
|
||||
|
||||
curve.style("display", state);
|
||||
d3.select(this).style(
|
||||
"fill", (state == "none") ? "none" : d.value.color
|
||||
);
|
||||
});
|
||||
|
||||
// Reposition and resize the box
|
||||
var lbbox = li[0][0].getBBox();
|
||||
lb.attr("x", (lbbox.x - legendPadding))
|
||||
.attr("y", (lbbox.y - legendPadding))
|
||||
.attr("height", (lbbox.height + 2 * legendPadding))
|
||||
.attr("width", (lbbox.width + 2 * legendPadding));
|
||||
});
|
||||
return g;
|
||||
};
|
||||
})();
|
||||
@@ -0,0 +1,355 @@
|
||||
/**
|
||||
* Creates an instance of ModoChart.
|
||||
*
|
||||
* @constructor
|
||||
* @this {ModoChart}
|
||||
* @param {string} selection add chart to this DOM element.
|
||||
*
|
||||
*/
|
||||
function ModoChart(selection) {
|
||||
var width = 0,
|
||||
height = 300,
|
||||
preview_height = 80,
|
||||
brush_height = 7,
|
||||
margin = {
|
||||
left: 50,
|
||||
top: 10,
|
||||
bottom: 20
|
||||
};
|
||||
var container;
|
||||
|
||||
/**
|
||||
* Create and render the chart.
|
||||
*
|
||||
* @this {ModoChart}
|
||||
* @param {Object} data chart's data.
|
||||
*/
|
||||
function my(data) {
|
||||
container = d3.select(selection)
|
||||
.append("div")
|
||||
.attr("class", "chart");
|
||||
|
||||
container.append("h6").html(data.title);
|
||||
width = $(selection).width();
|
||||
|
||||
var svg = container
|
||||
.append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", my.totalHeight());
|
||||
|
||||
svg.append("defs").append("clipPath")
|
||||
.attr("id", "clip")
|
||||
.append("rect")
|
||||
.attr("width", width - 2 * margin.left)
|
||||
.attr("height", height + margin.top + margin.bottom);
|
||||
|
||||
var x = d3.time.scale().range([0, width - 2 * margin.left]),
|
||||
x2 = d3.time.scale().range([0, width - 2 * margin.left]);
|
||||
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
|
||||
xAxis2 = d3.svg.axis().scale(x2).orient("bottom");
|
||||
var y = d3.scale.linear().range([height, 0]),
|
||||
y2 = d3.scale.linear().range([preview_height, 0]);
|
||||
var yAxis = d3.svg.axis().scale(y).orient("left");
|
||||
var bisectDate = d3.bisector(function(d) { return d.x * 1000; }).left;
|
||||
|
||||
var brush = d3.svg.brush()
|
||||
.x(x2)
|
||||
.on("brush", brushed);
|
||||
|
||||
x.domain(
|
||||
d3.extent(data.curves[0].data.map(function(d) { return d.x * 1000; }))
|
||||
);
|
||||
y.domain(
|
||||
[d3.min(data.curves, function(d) { return d3.min(d.data, function(v) { return v.y; }); }),
|
||||
d3.max(data.curves, function(d) { return d3.max(d.data, function(v) { return v.y; }); })
|
||||
]
|
||||
);
|
||||
x2.domain(x.domain());
|
||||
y2.domain(y.domain());
|
||||
|
||||
var area = d3.svg.area()
|
||||
.interpolate("monotone")
|
||||
.x(function(d) { return x(d.x * 1000); })
|
||||
.y0(height)
|
||||
.y1(function(d) { return y(d.y); });
|
||||
var area2 = d3.svg.area()
|
||||
.interpolate("monotone")
|
||||
.x(function(d) { return x2(d.x * 1000); })
|
||||
.y0(preview_height)
|
||||
.y1(function(d) { return y2(d.y); });
|
||||
|
||||
var focus = svg.append("g")
|
||||
.attr("class", "focus")
|
||||
.attr("width", width - 2 * margin.left)
|
||||
.attr("height", height)
|
||||
.attr("pointer-events", "all")
|
||||
.attr("transform",
|
||||
"translate(" + margin.left + "," + margin.top + ")");
|
||||
var context = svg.append("g")
|
||||
.attr("class", "context")
|
||||
.attr("transform", "translate(" + margin.left + "," + (height + margin.top + margin.bottom + brush_height) + ")");
|
||||
|
||||
var curvegroup = focus.append("g")
|
||||
.attr('clip-path', 'url(#clip)');
|
||||
var curve = curvegroup.selectAll(".curve")
|
||||
.data(data.curves)
|
||||
.enter().append("g")
|
||||
.attr("class", "curve");
|
||||
var curve2 = context.selectAll(".curve")
|
||||
.data(data.curves)
|
||||
.enter().append("g")
|
||||
.attr("class", "curve");
|
||||
|
||||
/* Vertical line */
|
||||
var line = focus.append("line")
|
||||
.attr("class", "line_over")
|
||||
.attr("x1", 0)
|
||||
.attr("y1", 0)
|
||||
.attr("x2", 0)
|
||||
.attr("y2", height);
|
||||
|
||||
/* Custom rectangle to catch mouse events */
|
||||
var rect = focus.append("rect")
|
||||
.attr("fill", "none")
|
||||
.attr("width", width - 2 * margin.left)
|
||||
.attr("height", height);
|
||||
|
||||
var tooltip = container
|
||||
.append("div")
|
||||
.attr("class", "remove")
|
||||
.attr("class", "tip");
|
||||
|
||||
var points = [];
|
||||
|
||||
var path = curve.append("path")
|
||||
.attr("class", "area")
|
||||
.attr("d", function(d, i) {
|
||||
var path = this;
|
||||
|
||||
points[path] = {};
|
||||
d.data.forEach(function(d) {
|
||||
points[path][d.x] = d.y;
|
||||
});
|
||||
focus.append("circle")
|
||||
.attr("class", "tracker tracker-" + i)
|
||||
.attr("r", 4);
|
||||
return area(d.data);
|
||||
})
|
||||
.attr("data-legend", function(d) { return d.name; })
|
||||
.attr("stroke", function(d) { return d.color; })
|
||||
.attr("stroke-width", "2px")
|
||||
.attr("stroke-opacity", 0.8)
|
||||
.style("fill", function(d) { return d.color; });
|
||||
|
||||
var xrules = make_x_axis();
|
||||
|
||||
focus.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xrules);
|
||||
focus.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_axis);
|
||||
focus.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis);
|
||||
focus.append("g")
|
||||
.attr("class", "y axis")
|
||||
.call(yAxis);
|
||||
|
||||
rect.on("mouseover", function(d) {
|
||||
line.style("display", "block");
|
||||
tooltip.style("display", "block");
|
||||
data.curves.forEach(function(d, cid) {
|
||||
var display = d3.selectAll("[data-legend='" + d.name + "']")
|
||||
.style("display");
|
||||
if (display == "none") {
|
||||
return;
|
||||
}
|
||||
focus.select(".tracker-" + cid).style("display", "block");
|
||||
});
|
||||
}).on("mousemove", function(d) {
|
||||
var mousex = d3.mouse(this)[0],
|
||||
mousey = d3.mouse(this)[1];
|
||||
var date = x.invert(mousex);
|
||||
var text = "";
|
||||
|
||||
line.attr("x1", mousex).attr("x2", mousex);
|
||||
data.curves.forEach(function(d, cid) {
|
||||
var display = d3.selectAll("[data-legend='" + d.name + "']")
|
||||
.style("display");
|
||||
if (display == "none") {
|
||||
return;
|
||||
}
|
||||
var i = bisectDate(d.data, date.getTime(), 1),
|
||||
d0 = d.data[i - 1],
|
||||
d1 = d.data[i],
|
||||
point = date.getTime() - (d0.x * 1000) > (d1.x * 1000) - date.getTime() ? d1 : d0;
|
||||
text += "<p>" + d.name + ": " + point.y.toFixed(3) + "</p>";
|
||||
|
||||
var tracker_x = x(point.x * 1000),
|
||||
tracker_y = y(point.y);
|
||||
|
||||
focus.selectAll(".tracker-" + cid)
|
||||
.style("fill", d.color)
|
||||
.attr("cx", tracker_x)
|
||||
.attr("cy", tracker_y);
|
||||
});
|
||||
if (mousex + tooltip[0][0].clientWidth >= width - 2 * margin.left) {
|
||||
var left = mousex - (tooltip[0][0].clientWidth - (margin.left - 20));
|
||||
tooltip.style("left", left + "px");
|
||||
} else {
|
||||
tooltip.style("left", (mousex + margin.left + 20) + "px");
|
||||
}
|
||||
tooltip.html("<p>" + date + "</p>" + text);
|
||||
}).on("mouseout", function(d) {
|
||||
tooltip.style("display", "none");
|
||||
line.style("display", "none");
|
||||
focus.selectAll(".tracker").style("display", "none");
|
||||
});
|
||||
|
||||
var legend = focus.append("g")
|
||||
.attr("class", "legend")
|
||||
.attr("transform", "translate(50,10)")
|
||||
.style("font-size", "0.8em")
|
||||
.call(d3.legend);
|
||||
|
||||
curve2.append("path")
|
||||
.attr("class", "area2")
|
||||
.attr("d", function(d) { return area2(d.data); })
|
||||
.attr("stroke", function(d) { return d.color; })
|
||||
.attr("stroke-width", "2px")
|
||||
.attr("stroke-opacity", 0.8)
|
||||
.attr("data-legend", function(d) { return d.name; })
|
||||
.style("fill", function(d) { return d.color; });
|
||||
|
||||
context.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + preview_height + ")")
|
||||
.call(xAxis2);
|
||||
|
||||
context.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + preview_height + ")")
|
||||
.call(make_preview_x_axis);
|
||||
|
||||
context.append("g")
|
||||
.attr("class", "x brush")
|
||||
.call(brush)
|
||||
.selectAll("rect")
|
||||
.attr("y", -6)
|
||||
.attr("height", preview_height + brush_height);
|
||||
|
||||
function make_x_axis() {
|
||||
return d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.ticks(6)
|
||||
.tickSize(-height, 0, 0)
|
||||
.tickFormat("");
|
||||
}
|
||||
|
||||
function make_y_axis() {
|
||||
return d3.svg.axis()
|
||||
.scale(y)
|
||||
.orient("left")
|
||||
.ticks(6)
|
||||
.tickSize(-(width - 2 * margin.left), 0, 0)
|
||||
.tickFormat("");
|
||||
}
|
||||
|
||||
function make_preview_x_axis() {
|
||||
return d3.svg.axis()
|
||||
.scale(x2)
|
||||
.orient("bottom")
|
||||
.ticks(6)
|
||||
.tickSize(-preview_height, 0, 0)
|
||||
.tickFormat("");
|
||||
}
|
||||
|
||||
function brushed() {
|
||||
x.domain(brush.empty() ? x2.domain() : brush.extent());
|
||||
focus.selectAll(".area")
|
||||
.attr("d", function(d) { return area(d.data); });
|
||||
focus.select(".x.axis").call(xAxis);
|
||||
focus.select(".grid").call(xrules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or get chart's width.
|
||||
*
|
||||
* @this {ModoChart}
|
||||
* @param {integer} value new width.
|
||||
* @return {number} current width.
|
||||
*/
|
||||
my.width = function(value) {
|
||||
if (!arguments.length) return width;
|
||||
width = value;
|
||||
return my;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set or get chart's height.
|
||||
*
|
||||
* @this {ModoChart}
|
||||
* @param {integer} value new height.
|
||||
* @return {number} current height.
|
||||
*/
|
||||
my.height = function(value) {
|
||||
if (!arguments.length) return height;
|
||||
height = value;
|
||||
return my;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set or get chart's margin.
|
||||
*
|
||||
* @this {ModoChart}
|
||||
* @param {Object} value new margin.
|
||||
* @return {Object} current margin.
|
||||
*/
|
||||
my.margin = function(value) {
|
||||
if (!arguments.length) return margin;
|
||||
margin = value;
|
||||
return my;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute and return chart's total height.
|
||||
*
|
||||
* @this {ModoChart}
|
||||
* @return {integer} total height.
|
||||
*/
|
||||
my.totalHeight = function() {
|
||||
return height + 2 * margin.top
|
||||
+ 2 * margin.bottom + preview_height
|
||||
+ brush_height;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the chart with new data.
|
||||
*
|
||||
* @this {ModoChart}
|
||||
* @param {Object} data new data
|
||||
*/
|
||||
my.update = function(data) {
|
||||
container.select("svg").remove();
|
||||
$(container[0][0]).empty();
|
||||
my(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the chart.
|
||||
*
|
||||
* @this {ModoChart}
|
||||
*/
|
||||
my.hide = function () {
|
||||
container.select("svg").remove();
|
||||
$(container[0][0]).empty();
|
||||
};
|
||||
|
||||
|
||||
return my;
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/**
|
||||
* Create an instance of Stats.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
var Stats = function(options) {
|
||||
this.initialize(options);
|
||||
};
|
||||
|
||||
Stats.prototype = {
|
||||
constructor: Stats,
|
||||
|
||||
defaults: {
|
||||
deflocation: "graphs/",
|
||||
language: "en",
|
||||
domain_list_url: null
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
this.options = $.extend({}, this.defaults, options);
|
||||
this.options.defcallback = $.proxy(this.charts_cb, this);
|
||||
|
||||
var navobj = new History(this.options);
|
||||
this.navobj = navobj;
|
||||
|
||||
this.charts = {};
|
||||
|
||||
if (navobj.params.searchquery !== undefined) {
|
||||
$("#searchquery").val(navobj.params.searchquery);
|
||||
}
|
||||
$("#searchquery").focus(function() {
|
||||
var $this = $(this);
|
||||
if ($this.val() === undefined) {
|
||||
return;
|
||||
}
|
||||
$this.data("oldvalue", $this.val());
|
||||
$this.val("");
|
||||
}).blur(function() {
|
||||
var $this = $(this);
|
||||
if ($this.val() === "") {
|
||||
if ($this.data("oldvalue")) {
|
||||
$this.val($this.data('oldvalue'));
|
||||
$this.data("oldvalue", null);
|
||||
} else {
|
||||
$this.val(gettext("Search a domain"));
|
||||
}
|
||||
}
|
||||
});
|
||||
if (navobj.params.start) {
|
||||
$("#id_from").val(navobj.params.start);
|
||||
}
|
||||
if (navobj.params.end) {
|
||||
$("#id_to").val(navobj.params.end);
|
||||
}
|
||||
if (navobj.params.period) {
|
||||
$("input[data-period={0}]".format(navobj.params.period))
|
||||
.attr("checked", true)
|
||||
.parent().addClass("active");
|
||||
if (navobj.params.period == "custom") {
|
||||
$("#custom_period").removeClass("hidden");
|
||||
}
|
||||
}
|
||||
$("#custom-period .datetime_picker").datetimepicker({
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
locale: this.options.language,
|
||||
ignoreReadonly: true
|
||||
});
|
||||
$("#searchquery").autocompleter({
|
||||
choices: $.proxy(this.get_domain_list, this),
|
||||
choice_selected: $.proxy(this.search_domain, this),
|
||||
empty_choice: $.proxy(this.reset_search, this)
|
||||
});
|
||||
|
||||
this.register_nav_callbacks();
|
||||
this.listen();
|
||||
},
|
||||
|
||||
listen: function() {
|
||||
$(".period_selector").click($.proxy(this.change_period, this));
|
||||
$("#customsend").on("click", $.proxy(this.custom_period, this));
|
||||
$(window).resize($.proxy(this.resize_charts, this));
|
||||
},
|
||||
|
||||
register_nav_callbacks: function() {
|
||||
this.navobj.register_callback("graphs",
|
||||
$.proxy(this.charts_cb, this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve a list of domain from the server.
|
||||
*/
|
||||
get_domain_list: function() {
|
||||
var result;
|
||||
|
||||
$.ajax({
|
||||
url: this.options.domain_list_url,
|
||||
dataType: "json",
|
||||
async: false
|
||||
}).done(function(data) {
|
||||
result = data;
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
change_period: function(e) {
|
||||
e.preventDefault();
|
||||
var $link = $(e.target).children("input");
|
||||
var period = $link.attr("data-period");
|
||||
|
||||
if (period != "custom") {
|
||||
$("#custom_period").addClass("hidden");
|
||||
this.navobj.delparam("start").delparam("end");
|
||||
this.navobj.setparam("period", $link.attr("data-period")).update();
|
||||
} else {
|
||||
$("#custom_period").removeClass("hidden");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update all charts on resize event.
|
||||
*
|
||||
* @this {Stats}
|
||||
*/
|
||||
resize_charts: function() {
|
||||
var data = this.data;
|
||||
$.each(this.charts, function(id, mychart) {
|
||||
mychart.update(data.graphs[id]);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Create or update charts.
|
||||
*
|
||||
* @this {Stats}
|
||||
* @param {Object} data
|
||||
*/
|
||||
charts_cb: function(data) {
|
||||
var menuid = "menu_" + this.navobj.getparam("gset");
|
||||
var activeCharts = new Array();
|
||||
|
||||
$(".nav-sidebar > li").removeClass("active");
|
||||
$("#" + menuid).addClass("active");
|
||||
this.data = data;
|
||||
if (!this.data.domain_selector) {
|
||||
$("#domain-selector").hide();
|
||||
} else {
|
||||
$("#domain-selector").show();
|
||||
}
|
||||
$.each(data.graphs, $.proxy(function(id, graphdef) {
|
||||
if (this.charts.hasOwnProperty(id)) {
|
||||
this.charts[id].update(graphdef);
|
||||
} else if (graphdef.curves.length) {
|
||||
var mychart = ModoChart("#gset");
|
||||
this.charts[id] = mychart;
|
||||
mychart(graphdef);
|
||||
}
|
||||
activeCharts.push(id);
|
||||
}, this));
|
||||
$.each(this.charts, function (id, mychart) {
|
||||
if (activeCharts.indexOf(id) === -1) {
|
||||
mychart.hide();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
search_domain: function(value) {
|
||||
this.navobj.setparam("searchquery", value).update();
|
||||
},
|
||||
|
||||
reset_search: function() {
|
||||
$("#searchquery").data("oldvalue", null);
|
||||
this.navobj.delparam("searchquery").update();
|
||||
},
|
||||
|
||||
custom_period: function(e) {
|
||||
e.preventDefault();
|
||||
var $fromdate = $("#id_from");
|
||||
var $todate = $("#id_to");
|
||||
|
||||
if ($fromdate.val() === "" || $todate.val() === "") {
|
||||
return;
|
||||
}
|
||||
this.navobj.setparams({
|
||||
period: "custom",
|
||||
start: $fromdate.val(),
|
||||
end: $todate.val()
|
||||
}).update();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
{% extends "twocols.html" %}
|
||||
{% load i18n static %}
|
||||
|
||||
{% block pagetitle %}{% trans "Graphical statistics" %}{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'maillog/css/stats.css' %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script type="text/javascript" src="{% static 'js/history.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/autocompleter.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'd3/d3.min.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'maillog/js/d3.legend.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'maillog/js/graphic.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'maillog/js/stats.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
var stats = new Stats({
|
||||
graphurl: "{% url 'maillog:graph_list' %}",
|
||||
domain_list_url: "{% url 'maillog:domain_list' %}",
|
||||
deflocation: "{{ deflocation|safe }}",
|
||||
language: "{{ LANGUAGE_CODE }}"
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block leftcol %}
|
||||
<ul class="nav nav-sidebar">
|
||||
{% for id, gset in graph_sets.items %}
|
||||
<li id="menu_{{ gset.html_id }}">
|
||||
<a href="#graphs?gset={{ gset.html_id }}">{{ gset.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block apparea %}
|
||||
<div id="menubar" class="row">
|
||||
<div id="domain-selector" class="col-sm-5">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div class="form-group has-feedback">
|
||||
<input class="form-control" id="searchquery" type="text" value="{% trans 'Search a domain' %}">
|
||||
<span class="fa fa-search form-control-feedback"></span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-7">
|
||||
<div class="btn-group" data-toggle="buttons">
|
||||
{% for p in periods %}
|
||||
<label class="btn btn-primary period_selector">
|
||||
<input type="radio" data-period="{{ p.name }}"> {% trans p.label %}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="custom_period" class="row hidden">
|
||||
<div class="col-sm-7">
|
||||
<form class="form-inline">
|
||||
<span id="custom-period">
|
||||
<div class="form-group">
|
||||
<div class="input-group datetime_picker">
|
||||
<div class="input-group-addon"><span class="fa fa-outdent"></span></div>
|
||||
<input id="id_from" name="date_form" class="form-control" value="{{ start }}" type="text" readonly="readonly">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group datetime_picker">
|
||||
<div class="input-group-addon"><span class="fa fa-outdent"></span></div>
|
||||
<input id="id_to" name="date_to" value="{{ end }}" class="form-control" type="text" readonly="readonly" />
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" id="customsend">{% trans "Apply" %}</button>
|
||||
</span>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="graphs">
|
||||
{% for id, gset in graph_sets.items %}
|
||||
<div class="tab-pane {% if forloop.first %}active{% endif %}" id="graphs_{{ gset.html_id }}">
|
||||
<div id="gset"></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,519 @@
|
||||
%(day)s 11:00:20 server postfix/cleanup[28945]: A0320E00C3: message-id=<cm.2100050552286.huticd.jyidyhxuy.y@cmail19.com>
|
||||
%(day)s 11:00:20 server postfix/qmgr[26163]: A0320E00C3: from=<visitbrussels-huticd1jyidyhxuy1y@cmail19.com>, size=142646, nrcpt=1 (queue active)
|
||||
%(day)s 11:00:20 server postfix/smtpd[28944]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:00:20 server amavis[14540]: (14540-09) Passed CLEAN {RelayedInbound}, [103.28.42.139]:56540 [103.28.42.139] <visitbrussels-huticd1jyidyhxuy1y@cmail19.com> -> <user@test.com>, Message-ID: <cm.2100050552286.huticd.jyidyhxuy.y@cmail19.com>, Hits: -1.481, size: 142067, queued_as: A0320E00C3, dkim_sd=cm:mailing.agenda.be, 10172 ms
|
||||
%(day)s 11:00:20 server postfix/smtpd[28914]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as A0320E00C3; from=<visitbrussels-huticd1jyidyhxuy1y@cmail19.com> to=<user@test.com> proto=ESMTP helo=<mx139.g.outbound.createsend.com>
|
||||
%(day)s 11:00:20 server dovecot: lmtp(30301): Connect from local
|
||||
%(day)s 11:00:20 server postfix/smtpd[28914]: disconnect from mx139.g.outbound.createsend.com[103.28.42.139] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
|
||||
%(day)s 11:00:20 server dovecot: lmtp(user@test.com): z5FOLrRhDVpddgAABvoInA: sieve: msgid=<cm.2100050552286.huticd.jyidyhxuy.y@cmail19.com>: stored mail into mailbox 'notifications'
|
||||
%(day)s 11:00:20 server postfix/lmtp[28946]: A0320E00C3: to=<user@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.32, delays=0.11/0.01/0.01/0.2, dsn=2.0.0, status=sent (250 2.0.0 <user@test.com> z5FOLrRhDVpddgAABvoInA Saved)
|
||||
%(day)s 11:00:20 server dovecot: lmtp(30301): Disconnect from local: Successful quit
|
||||
%(day)s 11:00:20 server postfix/qmgr[26163]: A0320E00C3: removed
|
||||
%(day)s 11:03:05 server postfix/postscreen[30620]: CONNECT from [207.154.235.157]:54810 to [94.23.45.181]:25
|
||||
%(day)s 11:03:11 server postfix/postscreen[30620]: PASS OLD [207.154.235.157]:54810
|
||||
%(day)s 11:03:12 server postfix/smtpd[30624]: connect from misas5.babino.pl[207.154.235.157]
|
||||
%(day)s 11:03:12 server postfix/smtpd[30624]: warning: 157.235.154.207.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=157.235.154.207.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:03:12 server postfix/cleanup[30637]: 2847EE008E: message-id=<20171116100312.2847EE008E@mail.koalabs.org>
|
||||
%(day)s 11:03:12 server postfix/qmgr[26163]: 2847EE008E: from=<double-bounce@mail.koalabs.org>, size=271, nrcpt=1 (queue active)
|
||||
%(day)s 11:03:12 server policyd-spf[30640]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=207.154.235.157; helo=misas5.babino.pl; envelope-from=zwroty@babino.pl; receiver=<UNKNOWN>
|
||||
%(day)s 11:03:12 server postfix/smtpd[30624]: NOQUEUE: client=misas5.babino.pl[207.154.235.157]
|
||||
%(day)s 11:03:15 server postfix/smtpd[30647]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:03:15 server postfix/smtpd[30647]: 1FEB7E00C4: client=localhost.localdomain[127.0.0.1], orig_client=misas5.babino.pl[207.154.235.157]
|
||||
%(day)s 11:03:15 server postfix/cleanup[30637]: 1FEB7E00C4: message-id=<de35d4cf3b0862e276fc1afc2f0c14d6@link.crazygecko.pl>
|
||||
%(day)s 11:03:15 server postfix/qmgr[26163]: 1FEB7E00C4: from=<zwroty@babino.pl>, size=53549, nrcpt=1 (queue active)
|
||||
%(day)s 11:03:15 server postfix/smtpd[30647]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:03:15 server amavis[19749]: (19749-18) Passed SPAM {RelayedTaggedInbound}, [207.154.235.157]:54810 [207.154.235.157] <zwroty@babino.pl> -> <info@test2.com>, Message-ID: <de35d4cf3b0862e276fc1afc2f0c14d6@link.crazygecko.pl>, Hits: 6.89, size: 52477, queued_as: 1FEB7E00C4, dkim_sd=1509955623.babino:babino.pl, 2365 ms
|
||||
%(day)s 11:03:15 server postfix/smtpd[30624]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 1FEB7E00C4; from=<zwroty@babino.pl> to=<info@test2.com> proto=ESMTP helo=<misas5.babino.pl>
|
||||
%(day)s 11:03:15 server postfix/smtpd[30624]: disconnect from misas5.babino.pl[207.154.235.157] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
|
||||
%(day)s 11:03:18 server postfix/smtp[30639]: Anonymous TLS connection established to mail.domain.test[94.23.191.34]:25: TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:03:18 server postfix/smtp[30639]: 2847EE008E: to=<info@test2.com>, relay=mail.domain.test[94.23.191.34]:25, delay=6.3, delays=0.04/0.01/6/0.19, dsn=2.1.5, status=deliverable (250 2.1.5 Ok)
|
||||
%(day)s 11:03:18 server postfix/qmgr[26163]: 2847EE008E: removed
|
||||
%(day)s 11:03:21 server postfix/smtp[30648]: Anonymous TLS connection established to mail.domain.test[94.23.191.34]:25: TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:03:26 server postfix/smtp[30648]: 1FEB7E00C4: to=<info@test2.com>, relay=mail.domain.test[94.23.191.34]:25, delay=11, delays=0.05/0.01/6.1/5.2, dsn=2.0.0, status=sent (250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 5DDDA1F30002)
|
||||
%(day)s 11:03:26 server postfix/qmgr[26163]: 1FEB7E00C4: removed
|
||||
%(day)s 11:04:01 server dovecot: imap-login: Login: user=<anomalie@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=30726, secured, session=<QlNHvRZeMMd/AAAB>
|
||||
%(day)s 11:04:01 server dovecot: imap(anomalie@test2.com): Logged out in=86 out=892
|
||||
%(day)s 11:04:01 server dovecot: imap-login: Login: user=<evolution@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=30742, secured, session=<2fBIvRZeMcd/AAAB>
|
||||
%(day)s 11:04:01 server dovecot: imap(evolution@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:04:01 server dovecot: imap-login: Login: user=<question@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=30754, secured, session=<YFdKvRZeMsd/AAAB>
|
||||
%(day)s 11:04:01 server dovecot: imap(question@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:04:15 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=30828, secured, session=<zUgbvhZeXcd/AAAB>
|
||||
%(day)s 11:04:18 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=30866, secured, session=<XKFHvhZeasd/AAAB>
|
||||
%(day)s 11:04:32 server postfix/postscreen[30620]: CONNECT from [127.0.0.1]:53903 to [127.0.0.1]:25
|
||||
%(day)s 11:04:32 server postfix/postscreen[30620]: WHITELISTED [127.0.0.1]:53903
|
||||
%(day)s 11:04:32 server postfix/smtpd[30624]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:04:32 server opendmarc[4245]: ignoring connection from localhost.localdomain
|
||||
%(day)s 11:04:32 server postfix/smtpd[30624]: NOQUEUE: client=localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:04:32 server postfix/smtpd[30647]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:04:32 server postfix/smtpd[30647]: 8D1B3E008E: client=localhost.localdomain[127.0.0.1], orig_client=localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:04:32 server postfix/cleanup[30637]: 8D1B3E008E: message-id=<20171116100432.10564.83744@server.ngyn.org>
|
||||
%(day)s 11:04:32 server postfix/smtpd[30647]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:04:32 server postfix/qmgr[26163]: 8D1B3E008E: from=<root@localhost>, size=18506, nrcpt=1 (queue active)
|
||||
%(day)s 11:04:32 server amavis[21816]: (21816-19) Passed CLEAN {RelayedInternal}, MYNETS LOCAL [127.0.0.1]:53903 <root@localhost> -> <admin@test.com>, Message-ID: <20171116100432.10564.83744@server.ngyn.org>, Hits: -, size: 18043, queued_as: 8D1B3E008E, 102 ms
|
||||
%(day)s 11:04:32 server postfix/smtpd[30624]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 8D1B3E008E; from=<root@localhost> to=<admin@test.com> proto=ESMTP helo=<server.ngyn.org>
|
||||
%(day)s 11:04:32 server postfix/smtpd[30624]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
|
||||
%(day)s 11:04:32 server dovecot: lmtp(30933): Connect from local
|
||||
%(day)s 11:04:32 server postfix/postscreen[30620]: CONNECT from [127.0.0.1]:53914 to [127.0.0.1]:25
|
||||
%(day)s 11:04:32 server postfix/postscreen[30620]: WHITELISTED [127.0.0.1]:53914
|
||||
%(day)s 11:04:32 server postfix/smtpd[30624]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:04:32 server opendmarc[4245]: ignoring connection from localhost.localdomain
|
||||
%(day)s 11:04:32 server postfix/smtpd[30624]: NOQUEUE: client=localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:04:32 server postfix/smtpd[30647]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:04:32 server postfix/smtpd[30647]: AA7FDE00C4: client=localhost.localdomain[127.0.0.1], orig_client=localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:04:32 server postfix/cleanup[30637]: AA7FDE00C4: message-id=<20171116100432.10564.58862@server.ngyn.org>
|
||||
%(day)s 11:04:32 server postfix/smtpd[30647]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:04:32 server postfix/qmgr[26163]: AA7FDE00C4: from=<root@localhost>, size=18506, nrcpt=1 (queue active)
|
||||
%(day)s 11:04:32 server amavis[5246]: (05246-16) Passed CLEAN {RelayedInternal}, MYNETS LOCAL [127.0.0.1]:53914 <root@localhost> -> <admin@test.com>, Message-ID: <20171116100432.10564.58862@server.ngyn.org>, Hits: -, size: 18043, queued_as: AA7FDE00C4, 79 ms
|
||||
%(day)s 11:04:32 server postfix/smtpd[30624]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as AA7FDE00C4; from=<root@localhost> to=<admin@test.com> proto=ESMTP helo=<server.ngyn.org>
|
||||
%(day)s 11:04:32 server postfix/smtpd[30624]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
|
||||
%(day)s 11:04:32 server dovecot: lmtp(30937): Connect from local
|
||||
%(day)s 11:04:32 server dovecot: lmtp(admin@test.com): cqWOJrBiDVrVeAAABvoInA: sieve: msgid=<20171116100432.10564.83744@server.ngyn.org>: stored mail into mailbox 'Koalabs'
|
||||
%(day)s 11:04:32 server dovecot: lmtp(30933): Disconnect from local: Successful quit
|
||||
%(day)s 11:04:32 server postfix/lmtp[30932]: 8D1B3E008E: to=<admin@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.26, delays=0.06/0.01/0.01/0.19, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> cqWOJrBiDVrVeAAABvoInA Saved)
|
||||
%(day)s 11:04:32 server postfix/qmgr[26163]: 8D1B3E008E: removed
|
||||
%(day)s 11:04:32 server dovecot: lmtp(admin@test.com): ES02LbBiDVrZeAAABvoInA: sieve: msgid=<20171116100432.10564.58862@server.ngyn.org>: stored mail into mailbox 'Koalabs'
|
||||
%(day)s 11:04:32 server dovecot: lmtp(30937): Disconnect from local: Successful quit
|
||||
%(day)s 11:04:32 server postfix/lmtp[30936]: AA7FDE00C4: to=<admin@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.22, delays=0.05/0/0.01/0.16, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> ES02LbBiDVrZeAAABvoInA Saved)
|
||||
%(day)s 11:04:32 server postfix/qmgr[26163]: AA7FDE00C4: removed
|
||||
%(day)s 11:06:45 server postfix/postscreen[31171]: CONNECT from [185.5.53.87]:58092 to [94.23.45.181]:25
|
||||
%(day)s 11:06:45 server postfix/postscreen[31171]: PASS OLD [185.5.53.87]:58092
|
||||
%(day)s 11:06:45 server postfix/smtpd[31172]: connect from main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:06:45 server postfix/smtpd[31172]: Anonymous TLS connection established from main.nope.org.es[185.5.53.87]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:06:45 server postfix/smtpd[31172]: warning: 87.53.5.185.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=87.53.5.185.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:06:46 server policyd-spf[31184]: prepend Received-SPF: None (no SPF record) identity=no SPF record; client-ip=185.5.53.87; helo=main.nope.org.es; envelope-from=<>; receiver=<UNKNOWN>
|
||||
%(day)s 11:06:46 server postfix/smtpd[31172]: NOQUEUE: client=main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:06:51 server postfix/smtpd[31201]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:06:51 server postfix/smtpd[31201]: AA3E6E00C3: client=localhost.localdomain[127.0.0.1], orig_client=main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:06:51 server postfix/cleanup[31202]: AA3E6E00C3: message-id=<201711161006.vAGA6jpH019527@main.nope.org.es>
|
||||
%(day)s 11:06:51 server postfix/smtpd[31201]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:06:51 server postfix/qmgr[26163]: AA3E6E00C3: from=<>, size=3194, nrcpt=1 (queue active)
|
||||
%(day)s 11:06:51 server amavis[14540]: (14540-10) Passed CLEAN {RelayedInbound}, [185.5.53.87]:58092 [185.5.53.87] <> -> <noreply@modoboa.org>, Message-ID: <201711161006.vAGA6jpH019527@main.nope.org.es>, Hits: -1.889, size: 2718, queued_as: AA3E6E00C3, 5178 ms
|
||||
%(day)s 11:06:51 server postfix/smtpd[31172]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as AA3E6E00C3; from=<> to=<noreply@modoboa.org> proto=ESMTP helo=<main.nope.org.es>
|
||||
%(day)s 11:06:51 server dovecot: lmtp(31204): Connect from local
|
||||
%(day)s 11:06:51 server dovecot: lmtp(admin@test.com): wUc3LDtjDVrkeQAABvoInA: sieve: msgid=<201711161006.vAGA6jpH019527@main.nope.org.es>: not sending reject message to <>
|
||||
%(day)s 11:06:51 server postfix/lmtp[31203]: AA3E6E00C3: to=<admin@test.com>, orig_to=<noreply@modoboa.org>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.07, delays=0.04/0.01/0.01/0.01, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> wUc3LDtjDVrkeQAABvoInA Saved)
|
||||
%(day)s 11:06:51 server dovecot: lmtp(31204): Disconnect from local: Successful quit
|
||||
%(day)s 11:06:51 server postfix/qmgr[26163]: AA3E6E00C3: removed
|
||||
%(day)s 11:06:52 server policyd-spf[31184]: prepend Received-SPF: None (no SPF record) identity=no SPF record; client-ip=185.5.53.87; helo=main.nope.org.es; envelope-from=<>; receiver=<UNKNOWN>
|
||||
%(day)s 11:06:52 server postfix/smtpd[31172]: NOQUEUE: client=main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:06:54 server postfix/smtpd[31201]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:06:54 server postfix/smtpd[31201]: 94D70E00C3: client=localhost.localdomain[127.0.0.1], orig_client=main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:06:54 server postfix/cleanup[31202]: 94D70E00C3: message-id=<201711161006.vAGA6jpI019527@main.nope.org.es>
|
||||
%(day)s 11:06:54 server postfix/smtpd[31201]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:06:54 server postfix/qmgr[26163]: 94D70E00C3: from=<>, size=2988, nrcpt=1 (queue active)
|
||||
%(day)s 11:06:54 server dovecot: lmtp(31204): Connect from local
|
||||
%(day)s 11:06:54 server dovecot: lmtp(admin@test.com): AQQ5Jz5jDVrkeQAABvoInA: sieve: msgid=<201711161006.vAGA6jpI019527@main.nope.org.es>: not sending reject message to <>
|
||||
%(day)s 11:06:54 server postfix/lmtp[31203]: 94D70E00C3: to=<admin@test.com>, orig_to=<noreply@modoboa.org>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.05, delays=0.05/0/0/0, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> AQQ5Jz5jDVrkeQAABvoInA Saved)
|
||||
%(day)s 11:06:54 server dovecot: lmtp(31204): Disconnect from local: Successful quit
|
||||
%(day)s 11:06:54 server postfix/qmgr[26163]: 94D70E00C3: removed
|
||||
%(day)s 11:06:54 server amavis[19749]: (19749-19) Passed CLEAN {RelayedInbound}, [185.5.53.87]:58092 [185.5.53.87] <> -> <noreply@modoboa.org>, Message-ID: <201711161006.vAGA6jpI019527@main.nope.org.es>, Hits: -1.889, size: 2512, queued_as: 94D70E00C3, 2262 ms
|
||||
%(day)s 11:06:54 server postfix/smtpd[31172]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 94D70E00C3; from=<> to=<noreply@modoboa.org> proto=ESMTP helo=<main.nope.org.es>
|
||||
%(day)s 11:06:54 server postfix/smtpd[31172]: disconnect from main.nope.org.es[185.5.53.87] ehlo=2 starttls=1 mail=2 rcpt=2 data=2 rset=1 quit=1 commands=11
|
||||
%(day)s 11:09:09 server postfix/anvil[28916]: statistics: max connection rate 1/60s for (smtpd:192.254.112.99) at %(day)s 10:59:09
|
||||
%(day)s 11:09:09 server postfix/anvil[28916]: statistics: max connection count 1 for (smtpd:192.254.112.99) at %(day)s 10:59:09
|
||||
%(day)s 11:09:09 server postfix/anvil[28916]: statistics: max cache size 3 at %(day)s 11:00:08
|
||||
%(day)s 11:10:02 server dovecot: imap-login: Login: user=<anomalie@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=31600, secured, session=<uVXK0hZeLMh/AAAB>
|
||||
%(day)s 11:10:02 server dovecot: imap(anomalie@test2.com): Logged out in=86 out=892
|
||||
%(day)s 11:10:02 server dovecot: imap-login: Login: user=<evolution@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=31618, secured, session=<VhXM0hZeLch/AAAB>
|
||||
%(day)s 11:10:02 server dovecot: imap(evolution@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:10:02 server dovecot: imap-login: Login: user=<question@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=31630, secured, session=<n4HN0hZeLsh/AAAB>
|
||||
%(day)s 11:10:02 server dovecot: imap(question@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:14:42 server postfix/postscreen[32096]: CONNECT from [51.15.3.241]:35169 to [94.23.45.181]:25
|
||||
%(day)s 11:14:42 server postfix/postscreen[32096]: PASS OLD [51.15.3.241]:35169
|
||||
%(day)s 11:14:42 server postfix/smtpd[32097]: warning: hostname 51-15-3-241.rev.poneytelecom.eu does not resolve to address 51.15.3.241: Name or service not known
|
||||
%(day)s 11:14:42 server postfix/smtpd[32097]: connect from unknown[51.15.3.241]
|
||||
%(day)s 11:14:42 server postfix/smtpd[32097]: Anonymous TLS connection established from unknown[51.15.3.241]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:14:42 server postfix/smtpd[32097]: warning: 241.3.15.51.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=241.3.15.51.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:14:43 server policyd-spf[32112]: prepend Received-SPF: None (mailfrom) identity=mailfrom; client-ip=51.15.3.241; helo=intra.logikap.com; envelope-from=gitlab@intra.logikap.com; receiver=<UNKNOWN>
|
||||
%(day)s 11:14:43 server postfix/smtpd[32097]: NOQUEUE: client=unknown[51.15.3.241]
|
||||
%(day)s 11:14:45 server postfix/smtpd[32119]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:14:45 server postfix/smtpd[32119]: 339B2E00C3: client=localhost.localdomain[127.0.0.1], orig_client=unknown[51.15.3.241]
|
||||
%(day)s 11:14:45 server postfix/cleanup[32120]: 339B2E00C3: message-id=<31819cf6c71e45f4569b94888ea90ead@gitlab.intra.logikap.com>
|
||||
%(day)s 11:14:45 server postfix/smtpd[32119]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:14:45 server postfix/qmgr[26163]: 339B2E00C3: from=<gitlab@intra.logikap.com>, size=3772, nrcpt=1 (queue active)
|
||||
%(day)s 11:14:45 server amavis[14540]: (14540-11) Passed CLEAN {RelayedInbound}, [51.15.3.241]:35169 [51.15.3.241] <gitlab@intra.logikap.com> -> <admin@test.com>, Message-ID: <31819cf6c71e45f4569b94888ea90ead@gitlab.intra.logikap.com>, Hits: -1.105, size: 3307, queued_as: 339B2E00C3, 1891 ms
|
||||
%(day)s 11:14:45 server postfix/smtpd[32097]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 339B2E00C3; from=<gitlab@intra.logikap.com> to=<admin@test.com> proto=ESMTP helo=<intra.logikap.com>
|
||||
%(day)s 11:14:45 server postfix/smtpd[32097]: disconnect from unknown[51.15.3.241] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:14:45 server dovecot: lmtp(32122): Connect from local
|
||||
%(day)s 11:14:45 server dovecot: lmtp(admin@test.com): +NuIEBVlDVp6fQAABvoInA: sieve: msgid=<31819cf6c71e45f4569b94888ea90ead@gitlab.intra.logikap.com>: stored mail into mailbox 'INBOX'
|
||||
%(day)s 11:14:45 server postfix/lmtp[32121]: 339B2E00C3: to=<admin@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.23, delays=0.06/0.01/0.01/0.16, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> +NuIEBVlDVp6fQAABvoInA Saved)
|
||||
%(day)s 11:14:45 server dovecot: lmtp(32122): Disconnect from local: Successful quit
|
||||
%(day)s 11:14:45 server postfix/qmgr[26163]: 339B2E00C3: removed
|
||||
%(day)s 11:16:01 server dovecot: imap(admin@test.com): Logged out in=3056 out=66597
|
||||
%(day)s 11:16:01 server dovecot: managesieve-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=32316, secured, session=<efcy6BZeE8h/AAAB>
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: Loading modules from directory: /usr/lib/dovecot/modules
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: Module loaded: /usr/lib/dovecot/modules/lib10_quota_plugin.so
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: Added userdb setting: plugin/quota_rule=*:bytes=2048M
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: Effective uid=1010, gid=1010, home=/srv/vmail/ngyn.org/tonio
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: Quota root: name=User quota backend=dict args=:proxy::quota
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: Quota rule: root=User quota mailbox=* bytes=2147483648 messages=0
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: Quota grace: root=User quota bytes=214748364 (10%%)
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: dict quota: user=admin@test.com, uri=proxy::quota, noenforcing=0
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: Namespace inbox: type=private, prefix=, sep=, inbox=yes, hidden=no, list=yes, subscriptions=yes location=maildir:~/.maildir
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: maildir++: root=/srv/vmail/ngyn.org/tonio/.maildir, index=, indexpvt=, control=, inbox=/srv/vmail/ngyn.org/tonio/.maildir, alt=
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: quota: quota_over_flag check: STORAGE ret=1 value=989542 limit=2097152
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: quota: quota_over_flag check: MESSAGE ret=0 value=47722 limit=0
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: quota: quota_over_flag=0((null)) vs currently overquota=0
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: sieve: Pigeonhole version 0.4.16 (fed8554) initializing
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: sieve: file storage: Using active Sieve script path: /srv/vmail/ngyn.org/tonio/.dovecot.sieve
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: sieve: file storage: Using script storage path: /srv/vmail/ngyn.org/tonio/sieve
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: sieve: file storage: Using permissions from /srv/vmail/ngyn.org/tonio/sieve: mode=0750 gid=-1
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: sieve: file storage: Relative path to sieve storage in active link: sieve/
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Debug: sieve: file storage: sync: Synchronization active
|
||||
%(day)s 11:16:01 server dovecot: managesieve(admin@test.com): Disconnected: Logged out bytes=6/41
|
||||
%(day)s 11:16:01 server dovecot: imap-login: Login: user=<anomalie@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=32327, secured, session=<Tc826BZe1ch/AAAB>
|
||||
%(day)s 11:16:01 server dovecot: imap(anomalie@test2.com): Logged out in=86 out=892
|
||||
%(day)s 11:16:01 server dovecot: imap-login: Login: user=<evolution@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=32345, secured, session=<2d046BZe1sh/AAAB>
|
||||
%(day)s 11:16:01 server dovecot: imap(evolution@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:16:02 server dovecot: imap-login: Login: user=<question@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=32359, secured, session=<XWM66BZe28h/AAAB>
|
||||
%(day)s 11:16:02 server dovecot: imap(question@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:16:03 server postfix/postscreen[32096]: CONNECT from [81.92.113.114]:60750 to [94.23.45.181]:25
|
||||
%(day)s 11:16:03 server postfix/postscreen[32096]: PASS OLD [81.92.113.114]:60750
|
||||
%(day)s 11:16:03 server postfix/smtpd[32097]: connect from mta1.news.tarsus.fr[81.92.113.114]
|
||||
%(day)s 11:16:03 server postfix/smtpd[32097]: warning: 114.113.92.81.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=114.113.92.81.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:16:03 server policyd-spf[32112]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=81.92.113.114; helo=mta1.news.tarsus.fr; envelope-from=marketing@info.opensourcesummit.paris; receiver=<UNKNOWN>
|
||||
%(day)s 11:16:03 server postfix/smtpd[32097]: NOQUEUE: client=mta1.news.tarsus.fr[81.92.113.114]
|
||||
%(day)s 11:16:04 server postfix/smtpd[32119]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:16:04 server postfix/smtpd[32119]: F39BCE00C3: client=localhost.localdomain[127.0.0.1], orig_client=mta1.news.tarsus.fr[81.92.113.114]
|
||||
%(day)s 11:16:04 server postfix/cleanup[32120]: F39BCE00C3: message-id=<2.1.4.1101006021.4688801.152618499@info.opensourcesummit.paris>
|
||||
%(day)s 11:16:05 server postfix/smtpd[32119]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:16:05 server postfix/qmgr[26163]: F39BCE00C3: from=<marketing@info.opensourcesummit.paris>, size=55627, nrcpt=1 (queue active)
|
||||
%(day)s 11:16:05 server amavis[19749]: (19749-20) Passed CLEAN {RelayedInbound}, [81.92.113.114]:60750 [81.92.113.114] <marketing@info.opensourcesummit.paris> -> <user@test.com>, Message-ID: <2.1.4.1101006021.4688801.152618499@info.opensourcesummit.paris>, Hits: 3.698, size: 54587, queued_as: F39BCE00C3, dkim_sd=emv:info.opensourcesummit.paris, 1310 ms
|
||||
%(day)s 11:16:05 server postfix/smtpd[32097]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as F39BCE00C3; from=<marketing@info.opensourcesummit.paris> to=<user@test.com> proto=ESMTP helo=<mta1.news.tarsus.fr>
|
||||
%(day)s 11:16:05 server dovecot: lmtp(32392): Connect from local
|
||||
%(day)s 11:16:05 server postfix/smtpd[32097]: disconnect from mta1.news.tarsus.fr[81.92.113.114] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
|
||||
%(day)s 11:16:05 server dovecot: lmtp(user@test.com): d8zmAmVlDVqIfgAABvoInA: sieve: msgid=<2.1.4.1101006021.4688801.152618499@info.opensourcesummit.paris>: stored mail into mailbox 'INBOX'
|
||||
%(day)s 11:16:05 server postfix/lmtp[32121]: F39BCE00C3: to=<user@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.23, delays=0.04/0.01/0.01/0.17, dsn=2.0.0, status=sent (250 2.0.0 <user@test.com> d8zmAmVlDVqIfgAABvoInA Saved)
|
||||
%(day)s 11:16:05 server dovecot: lmtp(32392): Disconnect from local: Successful quit
|
||||
%(day)s 11:16:05 server postfix/qmgr[26163]: F39BCE00C3: removed
|
||||
%(day)s 11:16:45 server dovecot: pop3-login: Login: user=<imhotep@koalabs.org>, method=PLAIN, rip=209.85.216.158, lip=94.23.45.181, mpid=32406, TLS, session=<AgHS6hZe1JnRVdie>
|
||||
%(day)s 11:16:45 server dovecot: pop3(imhotep@koalabs.org): Disconnected: Logged out top=0/0, retr=0/0, del=0/141, size=8023766
|
||||
%(day)s 11:17:01 server postfix/postscreen[32096]: CONNECT from [13.111.20.45]:47742 to [94.23.45.181]:25
|
||||
%(day)s 11:17:01 server postfix/postscreen[32096]: WHITELISTED [13.111.20.45]:47742
|
||||
%(day)s 11:17:01 server postfix/smtpd[32097]: connect from mta4.email.tfl.gov.uk[13.111.20.45]
|
||||
%(day)s 11:17:02 server postfix/smtpd[32097]: Anonymous TLS connection established from mta4.email.tfl.gov.uk[13.111.20.45]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:17:02 server postfix/smtpd[32097]: warning: 45.20.111.13.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=45.20.111.13.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:17:03 server policyd-spf[32112]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=13.111.20.45; helo=mta4.email.tfl.gov.uk; envelope-from=bounce-150_html-21457874-18921-100001609-123@bounce.email.tfl.gov.uk; receiver=<UNKNOWN>
|
||||
%(day)s 11:17:03 server postfix/smtpd[32097]: NOQUEUE: client=mta4.email.tfl.gov.uk[13.111.20.45]
|
||||
%(day)s 11:17:06 server postfix/smtpd[32119]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:17:06 server postfix/smtpd[32119]: 9E1C3E00C3: client=localhost.localdomain[127.0.0.1], orig_client=mta4.email.tfl.gov.uk[13.111.20.45]
|
||||
%(day)s 11:17:06 server postfix/cleanup[32120]: 9E1C3E00C3: message-id=<42e8ad52-02fb-45f5-a7fe-763c52409f6c@dfw1s10mta44.xt.local>
|
||||
%(day)s 11:17:08 server postfix/smtpd[32119]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:17:08 server postfix/qmgr[26163]: 9E1C3E00C3: from=<bounce-150_HTML-21457874-18921-100001609-123@bounce.email.tfl.gov.uk>, size=71561, nrcpt=1 (queue active)
|
||||
%(day)s 11:17:08 server amavis[5246]: (05246-17) Passed CLEAN {RelayedInbound}, [13.111.20.45]:47742 [13.111.20.45] <bounce-150_HTML-21457874-18921-100001609-123@bounce.email.tfl.gov.uk> -> <user@test.com>, Message-ID: <42e8ad52-02fb-45f5-a7fe-763c52409f6c@dfw1s10mta44.xt.local>, Hits: 2.492, size: 70304, queued_as: 9E1C3E00C3, dkim_sd=10dkim1:email.tfl.gov.uk, 3667 ms
|
||||
%(day)s 11:17:08 server postfix/smtpd[32097]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 9E1C3E00C3; from=<bounce-150_HTML-21457874-18921-100001609-123@bounce.email.tfl.gov.uk> to=<user@test.com> proto=ESMTP helo=<mta4.email.tfl.gov.uk>
|
||||
%(day)s 11:17:08 server dovecot: lmtp(32482): Connect from local
|
||||
%(day)s 11:17:08 server dovecot: lmtp(user@test.com): +IarBqRlDVrifgAABvoInA: sieve: msgid=<42e8ad52-02fb-45f5-a7fe-763c52409f6c@dfw1s10mta44.xt.local>: stored mail into mailbox 'INBOX'
|
||||
%(day)s 11:17:08 server postfix/lmtp[32121]: 9E1C3E00C3: to=<user@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=1.6, delays=1.5/0.01/0.01/0.17, dsn=2.0.0, status=sent (250 2.0.0 <user@test.com> +IarBqRlDVrifgAABvoInA Saved)
|
||||
%(day)s 11:17:08 server dovecot: lmtp(32482): Disconnect from local: Successful quit
|
||||
%(day)s 11:17:08 server postfix/qmgr[26163]: 9E1C3E00C3: removed
|
||||
%(day)s 11:17:08 server postfix/smtpd[32097]: disconnect from mta4.email.tfl.gov.uk[13.111.20.45] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:17:27 server postfix/postscreen[32096]: CONNECT from [51.254.143.19]:34827 to [94.23.45.181]:25
|
||||
%(day)s 11:17:33 server postfix/postscreen[32096]: NOQUEUE: reject: RCPT from [51.254.143.19]:34827: 450 4.3.2 Service currently unavailable; from=<szkoleniamanagerskie@machconsulting.eu>, to=<info@test2.com>, proto=ESMTP, helo=<vps373177.ovh.net>
|
||||
%(day)s 11:17:33 server postfix/postscreen[32096]: PASS NEW [51.254.143.19]:34827
|
||||
%(day)s 11:17:33 server postfix/postscreen[32096]: DISCONNECT [51.254.143.19]:34827
|
||||
%(day)s 11:17:43 server postfix/postscreen[32096]: CONNECT from [172.110.9.131]:37348 to [94.23.45.181]:25
|
||||
%(day)s 11:17:43 server postfix/postscreen[32096]: PASS OLD [172.110.9.131]:37348
|
||||
%(day)s 11:17:43 server postfix/smtpd[32097]: connect from unknown[172.110.9.131]
|
||||
%(day)s 11:17:43 server postfix/smtpd[32097]: Anonymous TLS connection established from unknown[172.110.9.131]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:17:43 server postfix/smtpd[32097]: warning: 131.9.110.172.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=131.9.110.172.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:17:44 server policyd-spf[32112]: prepend Received-SPF: None (no SPF record) identity=no SPF record; client-ip=172.110.9.131; helo=mailstore.paxi.cf; envelope-from=<>; receiver=<UNKNOWN>
|
||||
%(day)s 11:17:44 server postfix/smtpd[32097]: NOQUEUE: client=unknown[172.110.9.131]
|
||||
%(day)s 11:17:45 server postfix/smtpd[32119]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:17:45 server postfix/smtpd[32119]: 34B20E00C3: client=localhost.localdomain[127.0.0.1], orig_client=unknown[172.110.9.131]
|
||||
%(day)s 11:17:45 server postfix/cleanup[32120]: 34B20E00C3: message-id=<20171116101742.C6A924DCECC6@mailstore.paxi.cf>
|
||||
%(day)s 11:17:45 server postfix/smtpd[32119]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:17:45 server postfix/qmgr[26163]: 34B20E00C3: from=<>, size=4102, nrcpt=1 (queue active)
|
||||
%(day)s 11:17:45 server amavis[21816]: (21816-20) Passed CLEAN {RelayedInbound}, [172.110.9.131]:37348 [172.110.9.131] <> -> <noreply@modoboa.org>, Message-ID: <20171116101742.C6A924DCECC6@mailstore.paxi.cf>, Hits: -1.106, size: 3626, queued_as: 34B20E00C3, 1017 ms
|
||||
%(day)s 11:17:45 server dovecot: lmtp(32482): Connect from local
|
||||
%(day)s 11:17:45 server postfix/smtpd[32097]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 34B20E00C3; from=<> to=<noreply@modoboa.org> proto=ESMTP helo=<mailstore.paxi.cf>
|
||||
%(day)s 11:17:45 server dovecot: lmtp(admin@test.com): WQg7D8llDVrifgAABvoInA: sieve: msgid=<20171116101742.C6A924DCECC6@mailstore.paxi.cf>: not sending reject message to <>
|
||||
%(day)s 11:17:45 server postfix/lmtp[32121]: 34B20E00C3: to=<admin@test.com>, orig_to=<noreply@modoboa.org>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.05, delays=0.04/0.01/0/0, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> WQg7D8llDVrifgAABvoInA Saved)
|
||||
%(day)s 11:17:45 server dovecot: lmtp(32482): Disconnect from local: Successful quit
|
||||
%(day)s 11:17:45 server postfix/qmgr[26163]: 34B20E00C3: removed
|
||||
%(day)s 11:17:45 server postfix/postscreen[32096]: CONNECT from [108.174.3.154]:54018 to [94.23.45.181]:25
|
||||
%(day)s 11:17:45 server postfix/postscreen[32096]: WHITELISTED [108.174.3.154]:54018
|
||||
%(day)s 11:17:45 server postfix/smtpd[32097]: disconnect from unknown[172.110.9.131] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:17:45 server postfix/smtpd[32502]: connect from mailb-bb.linkedin.com[108.174.3.154]
|
||||
%(day)s 11:17:45 server postfix/smtpd[32502]: Anonymous TLS connection established from mailb-bb.linkedin.com[108.174.3.154]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:17:46 server postfix/smtpd[32502]: warning: 154.3.174.108.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=154.3.174.108.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:17:46 server policyd-spf[32505]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=108.174.3.154; helo=mailb-bb.linkedin.com; envelope-from=m-i58nvfj318qraba58ra9m2nttnwbk7s0evxwduql0g5d0pa6k36@bounce.linkedin.com; receiver=<UNKNOWN>
|
||||
%(day)s 11:17:46 server postfix/smtpd[32502]: NOQUEUE: client=mailb-bb.linkedin.com[108.174.3.154]
|
||||
%(day)s 11:17:47 server postfix/postscreen[32096]: CONNECT from [81.92.113.115]:43100 to [94.23.45.181]:25
|
||||
%(day)s 11:17:47 server postfix/postscreen[32096]: PASS OLD [81.92.113.115]:43100
|
||||
%(day)s 11:17:47 server postfix/smtpd[32097]: connect from mta2.news.tarsus.fr[81.92.113.115]
|
||||
%(day)s 11:17:47 server postfix/smtpd[32097]: warning: 115.113.92.81.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=115.113.92.81.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:17:48 server policyd-spf[32112]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=81.92.113.115; helo=mta2.news.tarsus.fr; envelope-from=marketing@info.opensourcesummit.paris; receiver=<UNKNOWN>
|
||||
%(day)s 11:17:48 server postfix/smtpd[32097]: NOQUEUE: client=mta2.news.tarsus.fr[81.92.113.115]
|
||||
%(day)s 11:17:52 server postfix/smtpd[32119]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:17:52 server postfix/smtpd[32119]: 69E9BE00C4: client=localhost.localdomain[127.0.0.1], orig_client=mailb-bb.linkedin.com[108.174.3.154]
|
||||
%(day)s 11:17:52 server postfix/cleanup[32120]: 69E9BE00C4: message-id=<205549081.609208.1510827464487.JavaMail.app@lor1-app2315.prod.linkedin.com>
|
||||
%(day)s 11:17:52 server postfix/smtpd[32119]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:17:52 server postfix/qmgr[26163]: 69E9BE00C4: from=<m-i58nvfj318qraba58ra9m2nttnwbk7s0evxwduql0g5d0pa6k36@bounce.linkedin.com>, size=35732, nrcpt=1 (queue active)
|
||||
%(day)s 11:17:52 server amavis[14540]: (14540-12) Passed CLEAN {RelayedInbound}, [108.174.3.154]:54018 [108.174.3.154] <m-i58nvfj318qraba58ra9m2nttnwbk7s0evxwduql0g5d0pa6k36@bounce.linkedin.com> -> <user@test.com>, Message-ID: <205549081.609208.1510827464487.JavaMail.app@lor1-app2315.prod.linkedin.com>, Hits: -7.019, size: 35066, queued_as: 69E9BE00C4, dkim_sd=proddkim1024:linkedin.com,proddkim1024:mailb.linkedin.com, 5477 ms
|
||||
%(day)s 11:17:52 server dovecot: lmtp(32482): Connect from local
|
||||
%(day)s 11:17:52 server postfix/smtpd[32502]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 69E9BE00C4; from=<m-i58nvfj318qraba58ra9m2nttnwbk7s0evxwduql0g5d0pa6k36@bounce.linkedin.com> to=<user@test.com> proto=ESMTP helo=<mailb-bb.linkedin.com>
|
||||
%(day)s 11:17:52 server dovecot: lmtp(user@test.com): UdRqG9BlDVrifgAABvoInA: sieve: msgid=<205549081.609208.1510827464487.JavaMail.app@lor1-app2315.prod.linkedin.com>: stored mail into mailbox 'INBOX'
|
||||
%(day)s 11:17:52 server postfix/lmtp[32121]: 69E9BE00C4: to=<user@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.16, delays=0.03/0.01/0/0.13, dsn=2.0.0, status=sent (250 2.0.0 <user@test.com> UdRqG9BlDVrifgAABvoInA Saved)
|
||||
%(day)s 11:17:52 server dovecot: lmtp(32482): Disconnect from local: Successful quit
|
||||
%(day)s 11:17:52 server postfix/qmgr[26163]: 69E9BE00C4: removed
|
||||
%(day)s 11:17:54 server postfix/smtpd[32119]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:17:54 server postfix/smtpd[32119]: 0EC0CE00C4: client=localhost.localdomain[127.0.0.1], orig_client=mta2.news.tarsus.fr[81.92.113.115]
|
||||
%(day)s 11:17:54 server postfix/cleanup[32120]: 0EC0CE00C4: message-id=<2.1.4.1101006021.4688801.3909372752@info.opensourcesummit.paris>
|
||||
%(day)s 11:17:54 server postfix/qmgr[26163]: 0EC0CE00C4: from=<marketing@info.opensourcesummit.paris>, size=55600, nrcpt=1 (queue active)
|
||||
%(day)s 11:17:54 server amavis[32393]: (32393-01) Passed CLEAN {RelayedInbound}, [81.92.113.115]:43100 [81.92.113.115] <marketing@info.opensourcesummit.paris> -> <admin@test.com>, Message-ID: <2.1.4.1101006021.4688801.3909372752@info.opensourcesummit.paris>, Hits: 3.507, size: 54590, queued_as: 0EC0CE00C4, dkim_sd=emv:info.opensourcesummit.paris, 5899 ms
|
||||
%(day)s 11:17:54 server dovecot: lmtp(32482): Connect from local
|
||||
%(day)s 11:17:54 server postfix/smtpd[32097]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 0EC0CE00C4; from=<marketing@info.opensourcesummit.paris> to=<admin@test.com> proto=ESMTP helo=<mta2.news.tarsus.fr>
|
||||
%(day)s 11:17:54 server postfix/smtpd[32097]: disconnect from mta2.news.tarsus.fr[81.92.113.115] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
|
||||
%(day)s 11:17:54 server dovecot: lmtp(admin@test.com): kRSZCNJlDVrifgAABvoInA: sieve: msgid=<2.1.4.1101006021.4688801.3909372752@info.opensourcesummit.paris>: stored mail into mailbox 'INBOX'
|
||||
%(day)s 11:17:54 server postfix/lmtp[32121]: 0EC0CE00C4: to=<admin@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.26, delays=0.09/0.01/0/0.17, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> kRSZCNJlDVrifgAABvoInA Saved)
|
||||
%(day)s 11:17:54 server dovecot: lmtp(32482): Disconnect from local: Successful quit
|
||||
%(day)s 11:17:54 server postfix/qmgr[26163]: 0EC0CE00C4: removed
|
||||
%(day)s 11:17:57 server postfix/smtpd[32502]: disconnect from mailb-bb.linkedin.com[108.174.3.154] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:18:26 server postfix/postscreen[32096]: CONNECT from [209.85.223.201]:46671 to [94.23.45.181]:25
|
||||
%(day)s 11:18:26 server postfix/postscreen[32096]: WHITELISTED [209.85.223.201]:46671
|
||||
%(day)s 11:18:26 server postfix/smtpd[32097]: connect from mail-io0-f201.google.com[209.85.223.201]
|
||||
%(day)s 11:18:26 server postfix/smtpd[32097]: Anonymous TLS connection established from mail-io0-f201.google.com[209.85.223.201]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
|
||||
%(day)s 11:18:26 server postfix/smtpd[32097]: warning: 201.223.85.209.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=201.223.85.209.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:18:26 server postfix/cleanup[32120]: E8BF5E00C4: message-id=<20171116101826.E8BF5E00C4@mail.koalabs.org>
|
||||
%(day)s 11:18:26 server postfix/qmgr[26163]: E8BF5E00C4: from=<double-bounce@mail.koalabs.org>, size=271, nrcpt=1 (queue active)
|
||||
%(day)s 11:18:27 server postfix/pipe[32592]: E8BF5E00C4: to=<dmarc-aggrep@ngyn.org>, relay=dmarc-rua, delay=0.04, delays=0.03/0.01/0/0.01, dsn=2.0.0, status=deliverable (delivers to command: /srv/modoboa/env/bin/python)
|
||||
%(day)s 11:18:27 server postfix/qmgr[26163]: E8BF5E00C4: removed
|
||||
%(day)s 11:18:27 server policyd-spf[32112]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.223.201; helo=mail-io0-f201.google.com; envelope-from=noreply-dmarc-support@google.com; receiver=<UNKNOWN>
|
||||
%(day)s 11:18:27 server postfix/smtpd[32097]: NOQUEUE: client=mail-io0-f201.google.com[209.85.223.201]
|
||||
%(day)s 11:18:28 server postfix/smtpd[32601]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:18:28 server postfix/smtpd[32601]: 5E852E00C4: client=localhost.localdomain[127.0.0.1], orig_client=mail-io0-f201.google.com[209.85.223.201]
|
||||
%(day)s 11:18:28 server postfix/cleanup[32120]: 5E852E00C4: message-id=<5520130506303437380@google.com>
|
||||
%(day)s 11:18:28 server postfix/smtpd[32601]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:18:28 server postfix/qmgr[26163]: 5E852E00C4: from=<noreply-dmarc-support@google.com>, size=4390, nrcpt=1 (queue active)
|
||||
%(day)s 11:18:28 server amavis[5246]: (05246-18) Passed CLEAN {RelayedInbound}, [209.85.223.201]:46671 [209.85.223.201] <noreply-dmarc-support@google.com> -> <dmarc-aggrep@ngyn.org>, Message-ID: <5520130506303437380@google.com>, Hits: 0.715, size: 3807, queued_as: 5E852E00C4, dkim_sd=20161025:google.com, 907 ms
|
||||
%(day)s 11:18:28 server postfix/smtpd[32097]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 5E852E00C4; from=<noreply-dmarc-support@google.com> to=<dmarc-aggrep@ngyn.org> proto=ESMTP helo=<mail-io0-f201.google.com>
|
||||
%(day)s 11:18:28 server postfix/smtpd[32097]: disconnect from mail-io0-f201.google.com[209.85.223.201] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:18:29 server postfix/pipe[32592]: 5E852E00C4: to=<dmarc-aggrep@ngyn.org>, relay=dmarc-rua, delay=0.85, delays=0.04/0/0/0.81, dsn=2.0.0, status=sent (delivered via dmarc-rua service (Importing report 5520130506303437380 received from google.com))
|
||||
%(day)s 11:18:29 server postfix/qmgr[26163]: 5E852E00C4: removed
|
||||
%(day)s 11:18:30 server postfix/postscreen[32096]: CONNECT from [193.105.248.56]:62968 to [94.23.45.181]:25
|
||||
%(day)s 11:18:36 server postfix/tlsproxy[32611]: CONNECT from [193.105.248.56]:62968
|
||||
%(day)s 11:18:38 server postfix/tlsproxy[32611]: Anonymous TLS connection established from [193.105.248.56]:62968: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:18:38 server postfix/postscreen[32096]: NOQUEUE: reject: RCPT from [193.105.248.56]:62968: 450 4.3.2 Service currently unavailable; from=<Kontakt@nestbank.pl>, to=<marcin.jurgielewicz@test2.com>, proto=ESMTP, helo=<mx01.nestbank.pl>
|
||||
%(day)s 11:18:38 server postfix/postscreen[32096]: PASS NEW [193.105.248.56]:62968
|
||||
%(day)s 11:18:38 server postfix/postscreen[32096]: DISCONNECT [193.105.248.56]:62968
|
||||
%(day)s 11:18:38 server postfix/tlsproxy[32611]: DISCONNECT [193.105.248.56]:62968
|
||||
%(day)s 11:19:59 server postfix/postscreen[32096]: CONNECT from [192.254.112.98]:6107 to [94.23.45.181]:25
|
||||
%(day)s 11:19:59 server postfix/postscreen[32096]: WHITELISTED [192.254.112.98]:6107
|
||||
%(day)s 11:19:59 server postfix/smtpd[32097]: connect from o3.sgmail.github.com[192.254.112.98]
|
||||
%(day)s 11:19:59 server postfix/smtpd[32097]: Anonymous TLS connection established from o3.sgmail.github.com[192.254.112.98]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
|
||||
%(day)s 11:20:00 server postfix/smtpd[32097]: warning: 98.112.254.192.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=98.112.254.192.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:20:00 server policyd-spf[32112]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=192.254.112.98; helo=o3.sgmail.github.com; envelope-from=bounces+848413-16c5-tonio=ngyn.org@sgmail.github.com; receiver=<UNKNOWN>
|
||||
%(day)s 11:20:00 server postfix/smtpd[32097]: NOQUEUE: client=o3.sgmail.github.com[192.254.112.98]
|
||||
%(day)s 11:20:07 server postfix/smtpd[32601]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:20:07 server postfix/smtpd[32601]: D9EA5E00C3: client=localhost.localdomain[127.0.0.1], orig_client=o3.sgmail.github.com[192.254.112.98]
|
||||
%(day)s 11:20:07 server postfix/cleanup[32120]: D9EA5E00C3: message-id=<Spicesoft/tandoori/pull/3047@github.com>
|
||||
%(day)s 11:20:07 server postfix/smtpd[32601]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:20:07 server postfix/qmgr[26163]: D9EA5E00C3: from=<bounces+848413-16c5-tonio=ngyn.org@sgmail.github.com>, size=12574, nrcpt=1 (queue active)
|
||||
%(day)s 11:20:07 server amavis[14540]: (14540-13) Passed CLEAN {RelayedInbound}, [192.254.112.98]:6107 [192.30.253.17] <bounces+848413-16c5-tonio=ngyn.org@sgmail.github.com> -> <admin@test.com>, Message-ID: <Spicesoft/tandoori/pull/3047@github.com>, Hits: -2.029, size: 11999, queued_as: D9EA5E00C3, dkim_sd=s20150108:github.com, 6918 ms
|
||||
%(day)s 11:20:07 server postfix/smtpd[32097]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as D9EA5E00C3; from=<bounces+848413-16c5-tonio=ngyn.org@sgmail.github.com> to=<admin@test.com> proto=ESMTP helo=<o3.sgmail.github.com>
|
||||
%(day)s 11:20:07 server dovecot: lmtp(323): Connect from local
|
||||
%(day)s 11:20:08 server dovecot: lmtp(admin@test.com): ZLuaN1dmDVpDAQAABvoInA: sieve: msgid=<Spicesoft/tandoori/pull/3047@github.com>: stored mail into mailbox 'Listes.Tandoori'
|
||||
%(day)s 11:20:08 server postfix/lmtp[322]: D9EA5E00C3: to=<admin@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.22, delays=0.03/0.01/0.01/0.17, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> ZLuaN1dmDVpDAQAABvoInA Saved)
|
||||
%(day)s 11:20:08 server dovecot: lmtp(323): Disconnect from local: Successful quit
|
||||
%(day)s 11:20:08 server postfix/qmgr[26163]: D9EA5E00C3: removed
|
||||
%(day)s 11:20:09 server postfix/smtpd[32097]: disconnect from o3.sgmail.github.com[192.254.112.98] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:20:50 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=336, secured, session=<BOJl+RZeUcl/AAAB>
|
||||
%(day)s 11:20:50 server dovecot: imap(admin@test.com): Logged out in=12 out=431
|
||||
%(day)s 11:20:50 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=350, secured, session=<W99o+RZeVMl/AAAB>
|
||||
%(day)s 11:20:50 server dovecot: imap(admin@test.com): Logged out in=12 out=431
|
||||
%(day)s 11:21:48 server dovecot: imap-login: Login: user=<mowee@modoboa.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=436, secured, session=<ZYje/BZeXcl/AAAB>
|
||||
%(day)s 11:21:48 server dovecot: imap(mowee@modoboa.com): Logged out in=12 out=431
|
||||
%(day)s 11:22:01 server dovecot: imap-login: Login: user=<anomalie@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=514, secured, session=<zeWs/RZeYsl/AAAB>
|
||||
%(day)s 11:22:01 server dovecot: imap(anomalie@test2.com): Logged out in=86 out=892
|
||||
%(day)s 11:22:01 server dovecot: imap-login: Login: user=<evolution@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=526, secured, session=<UKKu/RZeY8l/AAAB>
|
||||
%(day)s 11:22:02 server dovecot: imap(evolution@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:22:02 server dovecot: imap-login: Login: user=<question@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=538, secured, session=<jSmw/RZeZMl/AAAB>
|
||||
%(day)s 11:22:02 server dovecot: imap(question@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:22:54 server postfix/smtpd[32119]: timeout after END-OF-MESSAGE from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:22:54 server postfix/smtpd[32119]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 commands=5
|
||||
%(day)s 11:23:29 server postfix/anvil[32099]: statistics: max connection rate 1/60s for (smtpd:51.15.3.241) at %(day)s 11:14:42
|
||||
%(day)s 11:23:29 server postfix/anvil[32099]: statistics: max connection count 1 for (smtpd:51.15.3.241) at %(day)s 11:14:42
|
||||
%(day)s 11:23:29 server postfix/anvil[32099]: statistics: max cache size 4 at %(day)s 11:17:47
|
||||
%(day)s 11:26:26 server postfix/postscreen[916]: CONNECT from [167.89.55.170]:3520 to [94.23.45.181]:25
|
||||
%(day)s 11:26:26 server postfix/postscreen[916]: WHITELISTED [167.89.55.170]:3520
|
||||
%(day)s 11:26:26 server postfix/smtpd[917]: connect from o9.sendgrid.meetup.com[167.89.55.170]
|
||||
%(day)s 11:26:27 server postfix/smtpd[917]: Anonymous TLS connection established from o9.sendgrid.meetup.com[167.89.55.170]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
|
||||
%(day)s 11:26:28 server postfix/smtpd[917]: warning: 170.55.89.167.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=170.55.89.167.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:26:28 server policyd-spf[932]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=167.89.55.170; helo=o9.sendgrid.meetup.com; envelope-from=bounces+3922699-145a-tonio=ngyn.org@sendgrid.meetup.com; receiver=<UNKNOWN>
|
||||
%(day)s 11:26:28 server postfix/smtpd[917]: NOQUEUE: client=o9.sendgrid.meetup.com[167.89.55.170]
|
||||
%(day)s 11:26:36 server postfix/smtpd[944]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:26:36 server postfix/smtpd[944]: 61F9DE00C3: client=localhost.localdomain[127.0.0.1], orig_client=o9.sendgrid.meetup.com[167.89.55.170]
|
||||
%(day)s 11:26:36 server postfix/cleanup[945]: 61F9DE00C3: message-id=<710800146.1510827986412.JavaMail.root@1c1b55d0dbe0>
|
||||
%(day)s 11:26:36 server postfix/smtpd[944]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:26:36 server postfix/qmgr[26163]: 61F9DE00C3: from=<bounces+3922699-145a-tonio=ngyn.org@sendgrid.meetup.com>, size=72067, nrcpt=1 (queue active)
|
||||
%(day)s 11:26:36 server amavis[32393]: (32393-02) Passed CLEAN {RelayedInbound}, [167.89.55.170]:3520 [34.196.236.240] <bounces+3922699-145a-tonio=ngyn.org@sendgrid.meetup.com> -> <admin@test.com>, Message-ID: <710800146.1510827986412.JavaMail.root@1c1b55d0dbe0>, Hits: -2.221, size: 71500, queued_as: 61F9DE00C3, dkim_sd=s1:meetup.com, 7334 ms
|
||||
%(day)s 11:26:36 server postfix/smtpd[917]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 61F9DE00C3; from=<bounces+3922699-145a-tonio=ngyn.org@sendgrid.meetup.com> to=<admin@test.com> proto=ESMTP helo=<o9.sendgrid.meetup.com>
|
||||
%(day)s 11:26:36 server dovecot: lmtp(947): Connect from local
|
||||
%(day)s 11:26:36 server dovecot: lmtp(admin@test.com): f7GkHNxnDVqzAwAABvoInA: sieve: msgid=<710800146.1510827986412.JavaMail.root@1c1b55d0dbe0>: stored mail into mailbox 'INBOX'
|
||||
%(day)s 11:26:36 server postfix/lmtp[946]: 61F9DE00C3: to=<admin@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.28, delays=0.07/0.01/0.01/0.19, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> f7GkHNxnDVqzAwAABvoInA Saved)
|
||||
%(day)s 11:26:36 server dovecot: lmtp(947): Disconnect from local: Successful quit
|
||||
%(day)s 11:26:36 server postfix/qmgr[26163]: 61F9DE00C3: removed
|
||||
%(day)s 11:26:38 server postfix/smtpd[917]: disconnect from o9.sendgrid.meetup.com[167.89.55.170] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:28:01 server dovecot: imap-login: Login: user=<anomalie@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1109, secured, session=<CnAfExdevsl/AAAB>
|
||||
%(day)s 11:28:01 server dovecot: imap(anomalie@test2.com): Logged out in=86 out=892
|
||||
%(day)s 11:28:01 server dovecot: imap-login: Login: user=<evolution@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1125, secured, session=<fhohExdev8l/AAAB>
|
||||
%(day)s 11:28:01 server dovecot: imap(evolution@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:28:01 server dovecot: imap-login: Login: user=<question@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1137, secured, session=<+4AiExdewMl/AAAB>
|
||||
%(day)s 11:28:01 server dovecot: imap(question@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:29:58 server postfix/anvil[919]: statistics: max connection rate 1/60s for (smtpd:167.89.55.170) at %(day)s 11:26:26
|
||||
%(day)s 11:29:58 server postfix/anvil[919]: statistics: max connection count 1 for (smtpd:167.89.55.170) at %(day)s 11:26:26
|
||||
%(day)s 11:29:58 server postfix/anvil[919]: statistics: max cache size 1 at %(day)s 11:26:26
|
||||
%(day)s 11:30:30 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1406, secured, session=<CJn8Gxde5cl/AAAB>
|
||||
%(day)s 11:30:30 server dovecot: imap(admin@test.com): Logged out in=12 out=431
|
||||
%(day)s 11:30:30 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1420, secured, session=<rR4AHBde6Ml/AAAB>
|
||||
%(day)s 11:30:30 server dovecot: imap(admin@test.com): Logged out in=12 out=431
|
||||
%(day)s 11:30:34 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1436, secured, session=<lPE2HBde6cl/AAAB>
|
||||
%(day)s 11:30:34 server dovecot: imap(admin@test.com): Logged out in=12 out=431
|
||||
%(day)s 11:30:34 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1448, secured, session=<rfA6HBde6sl/AAAB>
|
||||
%(day)s 11:30:34 server dovecot: imap(admin@test.com): Logged out in=12 out=431
|
||||
%(day)s 11:32:47 server postfix/postscreen[1625]: CONNECT from [197.155.150.177]:16256 to [94.23.45.181]:25
|
||||
%(day)s 11:32:59 server postfix/postscreen[1625]: NOQUEUE: reject: RCPT from [197.155.150.177]:16256: 450 4.3.2 Service currently unavailable; from=<sion@sicli.ch>, to=<andrzej.patejuk@test2.com>, proto=ESMTP, helo=<[197.155.150.177]>
|
||||
%(day)s 11:32:59 server postfix/postscreen[1625]: HANGUP after 6.6 from [197.155.150.177]:16256 in tests after SMTP handshake
|
||||
%(day)s 11:32:59 server postfix/postscreen[1625]: PASS NEW [197.155.150.177]:16256
|
||||
%(day)s 11:32:59 server postfix/postscreen[1625]: DISCONNECT [197.155.150.177]:16256
|
||||
%(day)s 11:34:02 server dovecot: imap-login: Login: user=<anomalie@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1769, secured, session=<EIWbKBdeCMp/AAAB>
|
||||
%(day)s 11:34:02 server dovecot: imap(anomalie@test2.com): Logged out in=86 out=892
|
||||
%(day)s 11:34:02 server dovecot: imap-login: Login: user=<evolution@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1785, secured, session=<rDGdKBdeCcp/AAAB>
|
||||
%(day)s 11:34:02 server dovecot: imap(evolution@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:34:02 server dovecot: imap-login: Login: user=<question@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=1797, secured, session=<8peeKBdeCsp/AAAB>
|
||||
%(day)s 11:34:02 server dovecot: imap(question@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:35:07 server postfix/postscreen[1912]: CONNECT from [14.173.93.73]:55595 to [94.23.45.181]:25
|
||||
%(day)s 11:35:14 server postfix/postscreen[1912]: NOQUEUE: reject: RCPT from [14.173.93.73]:55595: 450 4.3.2 Service currently unavailable; from=<srdjan.sipus@sk.t-com.hr>, to=<andrzej.patejuk@test2.com>, proto=ESMTP, helo=<static.vnpt.vn>
|
||||
%(day)s 11:35:15 server postfix/postscreen[1912]: HANGUP after 1.4 from [14.173.93.73]:55595 in tests after SMTP handshake
|
||||
%(day)s 11:35:15 server postfix/postscreen[1912]: PASS NEW [14.173.93.73]:55595
|
||||
%(day)s 11:35:15 server postfix/postscreen[1912]: DISCONNECT [14.173.93.73]:55595
|
||||
%(day)s 11:36:00 server postfix/postscreen[1912]: CONNECT from [185.83.51.33]:58639 to [94.23.45.181]:25
|
||||
%(day)s 11:36:06 server postfix/tlsproxy[2011]: CONNECT from [185.83.51.33]:58639
|
||||
%(day)s 11:36:06 server postfix/tlsproxy[2011]: Anonymous TLS connection established from [185.83.51.33]:58639: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:36:07 server postfix/postscreen[1912]: NOQUEUE: reject: RCPT from [185.83.51.33]:58639: 450 4.3.2 Service currently unavailable; from=<mailreturn@smtp24.ymlpsvr.com>, to=<comercial@jm-motores.es>, proto=ESMTP, helo=<smtp24.ymlpsvr.com>
|
||||
%(day)s 11:36:07 server postfix/postscreen[1912]: PASS NEW [185.83.51.33]:58639
|
||||
%(day)s 11:36:07 server postfix/tlsproxy[2011]: DISCONNECT [185.83.51.33]:58639
|
||||
%(day)s 11:36:07 server postfix/postscreen[1912]: DISCONNECT [185.83.51.33]:58639
|
||||
%(day)s 11:36:45 server postfix/postscreen[1912]: CONNECT from [185.5.53.87]:50522 to [94.23.45.181]:25
|
||||
%(day)s 11:36:45 server postfix/postscreen[1912]: PASS OLD [185.5.53.87]:50522
|
||||
%(day)s 11:36:45 server postfix/smtpd[2027]: connect from main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:36:45 server postfix/smtpd[2027]: Anonymous TLS connection established from main.nope.org.es[185.5.53.87]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:36:46 server postfix/smtpd[2027]: warning: 87.53.5.185.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=87.53.5.185.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:36:46 server policyd-spf[2042]: prepend Received-SPF: None (no SPF record) identity=no SPF record; client-ip=185.5.53.87; helo=main.nope.org.es; envelope-from=<>; receiver=<UNKNOWN>
|
||||
%(day)s 11:36:46 server postfix/smtpd[2027]: NOQUEUE: client=main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:36:47 server postfix/smtpd[2051]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:36:47 server postfix/smtpd[2051]: E0B74E00C3: client=localhost.localdomain[127.0.0.1], orig_client=main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:36:47 server postfix/cleanup[2052]: E0B74E00C3: message-id=<201711161036.vAGAajZS022777@main.nope.org.es>
|
||||
%(day)s 11:36:47 server postfix/smtpd[2051]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:36:47 server postfix/qmgr[26163]: E0B74E00C3: from=<>, size=3195, nrcpt=1 (queue active)
|
||||
%(day)s 11:36:47 server amavis[14540]: (14540-14) Passed CLEAN {RelayedInbound}, [185.5.53.87]:50522 [185.5.53.87] <> -> <noreply@modoboa.org>, Message-ID: <201711161036.vAGAajZS022777@main.nope.org.es>, Hits: -1.889, size: 2719, queued_as: E0B74E00C3, 1212 ms
|
||||
%(day)s 11:36:47 server postfix/smtpd[2027]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as E0B74E00C3; from=<> to=<noreply@modoboa.org> proto=ESMTP helo=<main.nope.org.es>
|
||||
%(day)s 11:36:47 server dovecot: lmtp(2054): Connect from local
|
||||
%(day)s 11:36:47 server dovecot: lmtp(admin@test.com): e4pnOj9qDVoGCAAABvoInA: sieve: msgid=<201711161036.vAGAajZS022777@main.nope.org.es>: not sending reject message to <>
|
||||
%(day)s 11:36:47 server dovecot: lmtp(2054): Disconnect from local: Successful quit
|
||||
%(day)s 11:36:47 server postfix/lmtp[2053]: E0B74E00C3: to=<admin@test.com>, orig_to=<noreply@modoboa.org>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.08, delays=0.05/0.01/0.01/0.01, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> e4pnOj9qDVoGCAAABvoInA Saved)
|
||||
%(day)s 11:36:47 server postfix/qmgr[26163]: E0B74E00C3: removed
|
||||
%(day)s 11:36:48 server policyd-spf[2042]: prepend Received-SPF: None (no SPF record) identity=no SPF record; client-ip=185.5.53.87; helo=main.nope.org.es; envelope-from=<>; receiver=<UNKNOWN>
|
||||
%(day)s 11:36:48 server postfix/smtpd[2027]: NOQUEUE: client=main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:36:49 server postfix/smtpd[2051]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:36:49 server postfix/smtpd[2051]: 62D9BE00C3: client=localhost.localdomain[127.0.0.1], orig_client=main.nope.org.es[185.5.53.87]
|
||||
%(day)s 11:36:49 server postfix/cleanup[2052]: 62D9BE00C3: message-id=<201711161036.vAGAajZT022777@main.nope.org.es>
|
||||
%(day)s 11:36:49 server postfix/smtpd[2051]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:36:49 server postfix/qmgr[26163]: 62D9BE00C3: from=<>, size=2989, nrcpt=1 (queue active)
|
||||
%(day)s 11:36:49 server dovecot: lmtp(2054): Connect from local
|
||||
%(day)s 11:36:49 server dovecot: lmtp(admin@test.com): aVPzGUFqDVoGCAAABvoInA: sieve: msgid=<201711161036.vAGAajZT022777@main.nope.org.es>: not sending reject message to <>
|
||||
%(day)s 11:36:49 server postfix/lmtp[2053]: 62D9BE00C3: to=<admin@test.com>, orig_to=<noreply@modoboa.org>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.03, delays=0.03/0/0/0, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> aVPzGUFqDVoGCAAABvoInA Saved)
|
||||
%(day)s 11:36:49 server dovecot: lmtp(2054): Disconnect from local: Successful quit
|
||||
%(day)s 11:36:49 server postfix/qmgr[26163]: 62D9BE00C3: removed
|
||||
%(day)s 11:36:49 server amavis[32393]: (32393-03) Passed CLEAN {RelayedInbound}, [185.5.53.87]:50522 [185.5.53.87] <> -> <noreply@modoboa.org>, Message-ID: <201711161036.vAGAajZT022777@main.nope.org.es>, Hits: -1.889, size: 2513, queued_as: 62D9BE00C3, 955 ms
|
||||
%(day)s 11:36:49 server postfix/smtpd[2027]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 62D9BE00C3; from=<> to=<noreply@modoboa.org> proto=ESMTP helo=<main.nope.org.es>
|
||||
%(day)s 11:36:49 server postfix/smtpd[2027]: disconnect from main.nope.org.es[185.5.53.87] ehlo=2 starttls=1 mail=2 rcpt=2 data=2 rset=1 quit=1 commands=11
|
||||
%(day)s 11:38:49 server dovecot: imap-login: Login: user=<mowee@modoboa.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=2280, secured, session=<x0i8ORdeUsp/AAAB>
|
||||
%(day)s 11:38:49 server dovecot: imap(mowee@modoboa.com): Logged out in=12 out=431
|
||||
%(day)s 11:40:02 server dovecot: imap-login: Login: user=<anomalie@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=2474, secured, session=<MyUUPhdeYsp/AAAB>
|
||||
%(day)s 11:40:02 server dovecot: imap(anomalie@test2.com): Logged out in=86 out=892
|
||||
%(day)s 11:40:02 server dovecot: imap-login: Login: user=<evolution@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=2490, secured, session=<oScWPhdeZcp/AAAB>
|
||||
%(day)s 11:40:02 server dovecot: imap(evolution@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:40:02 server dovecot: imap-login: Login: user=<question@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=2502, secured, session=<3Y0XPhdeZsp/AAAB>
|
||||
%(day)s 11:40:02 server dovecot: imap(question@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:40:09 server postfix/anvil[2029]: statistics: max connection rate 1/60s for (smtpd:185.5.53.87) at %(day)s 11:36:45
|
||||
%(day)s 11:40:09 server postfix/anvil[2029]: statistics: max connection count 1 for (smtpd:185.5.53.87) at %(day)s 11:36:45
|
||||
%(day)s 11:40:09 server postfix/anvil[2029]: statistics: max cache size 1 at %(day)s 11:36:45
|
||||
%(day)s 11:43:42 server dovecot: imap(admin@test.com): Disconnected for inactivity in=1797 out=54357
|
||||
%(day)s 11:44:20 server postfix/postscreen[2852]: CONNECT from [192.254.113.101]:53977 to [94.23.45.181]:25
|
||||
%(day)s 11:44:20 server postfix/postscreen[2852]: WHITELISTED [192.254.113.101]:53977
|
||||
%(day)s 11:44:20 server postfix/smtpd[2853]: connect from o6.sgmail.github.com[192.254.113.101]
|
||||
%(day)s 11:44:20 server postfix/smtpd[2853]: Anonymous TLS connection established from o6.sgmail.github.com[192.254.113.101]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
|
||||
%(day)s 11:44:21 server postfix/smtpd[2853]: warning: 101.113.254.192.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=101.113.254.192.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:44:21 server policyd-spf[2868]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=192.254.113.101; helo=o6.sgmail.github.com; envelope-from=bounces+848413-16c5-tonio=ngyn.org@sgmail.github.com; receiver=<UNKNOWN>
|
||||
%(day)s 11:44:21 server postfix/smtpd[2853]: NOQUEUE: client=o6.sgmail.github.com[192.254.113.101]
|
||||
%(day)s 11:44:31 server postfix/smtpd[2878]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:44:31 server postfix/smtpd[2878]: 70959E00C3: client=localhost.localdomain[127.0.0.1], orig_client=o6.sgmail.github.com[192.254.113.101]
|
||||
%(day)s 11:44:31 server postfix/cleanup[2879]: 70959E00C3: message-id=<Spicesoft/tandoori/pull/3047/c344885124@github.com>
|
||||
%(day)s 11:44:31 server postfix/smtpd[2878]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:44:31 server postfix/qmgr[26163]: 70959E00C3: from=<bounces+848413-16c5-tonio=ngyn.org@sgmail.github.com>, size=9954, nrcpt=1 (queue active)
|
||||
%(day)s 11:44:31 server amavis[14540]: (14540-15) Passed CLEAN {RelayedInbound}, [192.254.113.101]:53977 [192.30.253.16] <bounces+848413-16c5-tonio=ngyn.org@sgmail.github.com> -> <admin@test.com>, Message-ID: <Spicesoft/tandoori/pull/3047/c344885124@github.com>, Hits: -2.22, size: 9378, queued_as: 70959E00C3, dkim_sd=s20150108:github.com, 9468 ms
|
||||
%(day)s 11:44:31 server postfix/smtpd[2853]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as 70959E00C3; from=<bounces+848413-16c5-tonio=ngyn.org@sgmail.github.com> to=<admin@test.com> proto=ESMTP helo=<o6.sgmail.github.com>
|
||||
%(day)s 11:44:31 server dovecot: lmtp(2881): Connect from local
|
||||
%(day)s 11:44:31 server dovecot: lmtp(admin@test.com): FmU3Hg9sDVpBCwAABvoInA: sieve: msgid=<Spicesoft/tandoori/pull/3047/c344885124@github.com>: stored mail into mailbox 'Listes.Tandoori'
|
||||
%(day)s 11:44:31 server postfix/lmtp[2880]: 70959E00C3: to=<admin@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.2, delays=0.04/0.01/0.01/0.14, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> FmU3Hg9sDVpBCwAABvoInA Saved)
|
||||
%(day)s 11:44:31 server dovecot: lmtp(2881): Disconnect from local: Successful quit
|
||||
%(day)s 11:44:31 server postfix/qmgr[26163]: 70959E00C3: removed
|
||||
%(day)s 11:44:33 server postfix/smtpd[2853]: disconnect from o6.sgmail.github.com[192.254.113.101] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:46:01 server dovecot: imap-login: Login: user=<anomalie@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=3041, secured, session=<wWyAUxdeusp/AAAB>
|
||||
%(day)s 11:46:01 server dovecot: imap(anomalie@test2.com): Logged out in=86 out=892
|
||||
%(day)s 11:46:01 server dovecot: imap-login: Login: user=<evolution@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=3057, secured, session=<YASCUxdeu8p/AAAB>
|
||||
%(day)s 11:46:01 server dovecot: imap(evolution@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:46:01 server dovecot: imap-login: Login: user=<question@test2.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=3069, secured, session=<6mqDUxdevMp/AAAB>
|
||||
%(day)s 11:46:02 server dovecot: imap(question@test2.com): Logged out in=86 out=891
|
||||
%(day)s 11:47:16 server postfix/postscreen[3161]: CONNECT from [37.187.155.42]:33450 to [94.23.45.181]:25
|
||||
%(day)s 11:47:22 server postfix/tlsproxy[3164]: CONNECT from [37.187.155.42]:33450
|
||||
%(day)s 11:47:22 server postfix/tlsproxy[3164]: Anonymous TLS connection established from [37.187.155.42]:33450: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:47:22 server postfix/postscreen[3161]: NOQUEUE: reject: RCPT from [37.187.155.42]:33450: 450 4.3.2 Service currently unavailable; from=<rebotes@cursosfemxa.es>, to=<comercial@jm-motores.es>, proto=ESMTP, helo=<cursosfemxa.es>
|
||||
%(day)s 11:47:22 server postfix/postscreen[3161]: PASS NEW [37.187.155.42]:33450
|
||||
%(day)s 11:47:22 server postfix/postscreen[3161]: DISCONNECT [37.187.155.42]:33450
|
||||
%(day)s 11:47:22 server postfix/tlsproxy[3164]: DISCONNECT [37.187.155.42]:33450
|
||||
%(day)s 11:47:42 server postfix/postscreen[3161]: CONNECT from [172.110.9.131]:58398 to [94.23.45.181]:25
|
||||
%(day)s 11:47:42 server postfix/postscreen[3161]: PASS OLD [172.110.9.131]:58398
|
||||
%(day)s 11:47:43 server postfix/smtpd[3182]: connect from unknown[172.110.9.131]
|
||||
%(day)s 11:47:43 server postfix/smtpd[3182]: Anonymous TLS connection established from unknown[172.110.9.131]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
|
||||
%(day)s 11:47:43 server postfix/smtpd[3182]: warning: 131.9.110.172.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=131.9.110.172.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 11:47:44 server policyd-spf[3195]: prepend Received-SPF: None (no SPF record) identity=no SPF record; client-ip=172.110.9.131; helo=mailstore.paxi.cf; envelope-from=<>; receiver=<UNKNOWN>
|
||||
%(day)s 11:47:44 server postfix/smtpd[3182]: NOQUEUE: client=unknown[172.110.9.131]
|
||||
%(day)s 11:47:45 server postfix/smtpd[3202]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 11:47:45 server postfix/smtpd[3202]: E81D5E00C3: client=localhost.localdomain[127.0.0.1], orig_client=unknown[172.110.9.131]
|
||||
%(day)s 11:47:45 server postfix/cleanup[3203]: E81D5E00C3: message-id=<20171116104742.7CC0E4DCECC7@mailstore.paxi.cf>
|
||||
%(day)s 11:47:45 server postfix/smtpd[3202]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 11:47:45 server postfix/qmgr[26163]: E81D5E00C3: from=<>, size=4166, nrcpt=1 (queue active)
|
||||
%(day)s 11:47:45 server amavis[32393]: (32393-04) Passed CLEAN {RelayedInbound}, [172.110.9.131]:58398 [172.110.9.131] <> -> <noreply@modoboa.org>, Message-ID: <20171116104742.7CC0E4DCECC7@mailstore.paxi.cf>, Hits: -1.106, size: 3690, queued_as: E81D5E00C3, 1410 ms
|
||||
%(day)s 11:47:45 server postfix/smtpd[3182]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as E81D5E00C3; from=<> to=<noreply@modoboa.org> proto=ESMTP helo=<mailstore.paxi.cf>
|
||||
%(day)s 11:47:46 server dovecot: lmtp(3205): Connect from local
|
||||
%(day)s 11:47:46 server dovecot: lmtp(admin@test.com): RTETANJsDVqFDAAABvoInA: sieve: msgid=<20171116104742.7CC0E4DCECC7@mailstore.paxi.cf>: not sending reject message to <>
|
||||
%(day)s 11:47:46 server postfix/lmtp[3204]: E81D5E00C3: to=<admin@test.com>, orig_to=<noreply@modoboa.org>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.07, delays=0.04/0.01/0.01/0, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> RTETANJsDVqFDAAABvoInA Saved)
|
||||
%(day)s 11:47:46 server dovecot: lmtp(3205): Disconnect from local: Successful quit
|
||||
%(day)s 11:47:46 server postfix/qmgr[26163]: E81D5E00C3: removed
|
||||
%(day)s 11:47:46 server postfix/smtpd[3182]: disconnect from unknown[172.110.9.131] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7
|
||||
%(day)s 11:50:50 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=3536, secured, session=<PwOvZBdeI8t/AAAB>
|
||||
%(day)s 11:50:50 server dovecot: imap(admin@test.com): Logged out in=12 out=431
|
||||
%(day)s 11:50:50 server dovecot: imap-login: Login: user=<admin@test.com>, method=PLAIN, rip=127.0.0.1, lip=127.0.0.1, mpid=3551, secured, session=<0rGyZBdeJst/AAAB>
|
||||
%(day)s 11:50:50 server dovecot: imap(admin@test.com): Logged out in=12 out=431
|
||||
%(day)s 14:40:58 server postfix/postscreen[27044]: CONNECT from [188.213.142.238]:42388 to [94.23.45.181]:25
|
||||
%(day)s 14:40:58 server postfix/postscreen[27044]: PASS OLD [188.213.142.238]:42388
|
||||
%(day)s 14:40:58 server postfix/smtpd[27045]: connect from c264-2.lesmails.info[188.213.142.238]
|
||||
%(day)s 14:40:58 server postfix/smtpd[27045]: warning: 238.142.213.188.zen.spamhaus.org: RBL lookup error: Host or domain name not found. Name service error for name=238.142.213.188.zen.spamhaus.org type=A: Host not found, try again
|
||||
%(day)s 14:40:59 server policyd-spf[27066]: prepend Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=188.213.142.238; helo=sender.234.com; envelope-from=no-reply@mailing-lowcost.fr; receiver=<UNKNOWN>
|
||||
%(day)s 14:40:59 server postfix/smtpd[27045]: NOQUEUE: client=c264-2.lesmails.info[188.213.142.238]
|
||||
%(day)s 14:41:00 server postfix/smtpd[27073]: connect from localhost.localdomain[127.0.0.1]
|
||||
%(day)s 14:41:00 server postfix/smtpd[27073]: C2E3BE00C3: client=localhost.localdomain[127.0.0.1], orig_client=c264-2.lesmails.info[188.213.142.238]
|
||||
%(day)s 14:41:00 server postfix/cleanup[27074]: C2E3BE00C3: message-id=<20171116131143.F75320333C@JM6_EVENTS.home>
|
||||
%(day)s 14:41:00 server postfix/smtpd[27073]: disconnect from localhost.localdomain[127.0.0.1] ehlo=1 xforward=1 mail=1 rcpt=1 data=1 quit=1 commands=6
|
||||
%(day)s 14:41:00 server postfix/qmgr[26163]: C2E3BE00C3: from=<no-reply@mailing-lowcost.fr>, size=97952, nrcpt=1 (queue active)
|
||||
%(day)s 14:41:00 server amavis[8518]: (08518-10) Passed SPAM {RelayedTaggedInbound}, [188.213.142.238]:42388 [188.213.142.238] <no-reply@mailing-lowcost.fr> -> <alias@test.com>, Message-ID: <20171116131143.F75320333C@jm6_events.home>, Hits: 13.086, size: 96743, queued_as: C2E3BE00C3, 1258 ms
|
||||
%(day)s 14:41:00 server postfix/smtpd[27045]: proxy-accept: END-OF-MESSAGE: 250 2.0.0 from MTA(smtp:[127.0.0.1]:10025): 250 2.0.0 Ok: queued as C2E3BE00C3; from=<no-reply@mailing-lowcost.fr> to=<alias@test.com> proto=ESMTP helo=<sender.234.com>
|
||||
%(day)s 14:41:00 server postfix/smtpd[27045]: disconnect from c264-2.lesmails.info[188.213.142.238] ehlo=1 mail=1 rcpt=1 data=1 quit=1 commands=5
|
||||
%(day)s 14:41:00 server dovecot: lmtp(27260): Connect from local
|
||||
%(day)s 14:41:01 server dovecot: lmtp(admin@test.com): +TSvNWyVDVp8agAABvoInA: sieve: msgid=<20171116131143.F75320333C@JM6_EVENTS.home>: stored mail into mailbox 'Junk'
|
||||
%(day)s 14:41:01 server postfix/lmtp[27075]: C2E3BE00C3: to=<admin@test.com>, orig_to=<alias@test.com>, relay=mail.koalabs.org[private/dovecot-lmtp], delay=0.29, delays=0.09/0.01/0.01/0.18, dsn=2.0.0, status=sent (250 2.0.0 <admin@test.com> +TSvNWyVDVp8agAABvoInA Saved)
|
||||
%(day)s 14:41:01 server dovecot: lmtp(27260): Disconnect from local: Successful quit
|
||||
%(day)s 14:41:01 server postfix/qmgr[26163]: C2E3BE00C3: removed
|
||||
@@ -0,0 +1,168 @@
|
||||
"""modoboa-stats tests."""
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.urls import reverse
|
||||
from django.test import override_settings
|
||||
|
||||
from modoboa.admin import factories as admin_factories
|
||||
from modoboa.core import models as core_models
|
||||
from modoboa.lib.tests import ModoTestCase
|
||||
|
||||
|
||||
class RunCommandsMixin(object):
|
||||
"""Mixin to run management commands."""
|
||||
|
||||
def setUp(self):
|
||||
super(RunCommandsMixin, self).setUp()
|
||||
self.workdir = tempfile.mkdtemp()
|
||||
self.set_global_parameter("rrd_rootdir", self.workdir)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.workdir)
|
||||
|
||||
def run_logparser(self):
|
||||
"""Run logparser command."""
|
||||
path = os.path.join(
|
||||
os.path.dirname(__file__), "mail.log")
|
||||
with open(path) as fp:
|
||||
content = fp.read() % {
|
||||
"day": datetime.date.today().strftime("%b %d")}
|
||||
path = os.path.join(self.workdir, "mail.log")
|
||||
with open(path, "w") as fp:
|
||||
fp.write(content)
|
||||
self.set_global_parameter("logfile", path)
|
||||
call_command("logparser")
|
||||
|
||||
def run_update_statistics(self, rebuild=False):
|
||||
"""Run update_statistics command."""
|
||||
args = []
|
||||
if rebuild:
|
||||
args.append("--rebuild")
|
||||
call_command("update_statistics", *args)
|
||||
|
||||
|
||||
@override_settings(RRDTOOL_TEST_MODE=True)
|
||||
class ViewsTestCase(RunCommandsMixin, ModoTestCase):
|
||||
"""Views test cases."""
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls): # noqa
|
||||
super(ViewsTestCase, cls).setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
cls.da = core_models.User.objects.get(username="admin@test.com")
|
||||
|
||||
def tearDown(self):
|
||||
super(ViewsTestCase, self).tearDown()
|
||||
self.set_global_parameter("greylist", False)
|
||||
|
||||
def test_index(self):
|
||||
"""Test index view."""
|
||||
url = reverse("maillog:fullindex")
|
||||
response = self.client.get(url)
|
||||
self.assertContains(response, 'id="graphs_accountgraphicset"')
|
||||
self.assertContains(response, 'id="graphs_mailtraffic"')
|
||||
|
||||
self.client.force_login(self.da)
|
||||
response = self.client.get(url)
|
||||
self.assertContains(response, 'id="graphs_mailtraffic"')
|
||||
|
||||
def test_graphs(self):
|
||||
"""Test graphs views."""
|
||||
self.run_logparser()
|
||||
url = reverse("maillog:graph_list")
|
||||
self.ajax_get(url, status=404)
|
||||
response = self.ajax_get("{}?gset=mailtraffic".format(url))
|
||||
self.assertIn("averagetraffic", response["graphs"])
|
||||
for period in ["week", "month", "year"]:
|
||||
response = self.ajax_get(
|
||||
"{}?gset=mailtraffic&period={}".format(url, period))
|
||||
self.assertIn("averagetraffic", response["graphs"])
|
||||
self.assertEqual(response["period_name"], period)
|
||||
|
||||
# custom period
|
||||
today = datetime.date.today()
|
||||
start = "{} 11:00:00".format(today)
|
||||
end = "{} 11:40:00".format(today)
|
||||
response = self.ajax_get(
|
||||
"{}?gset=mailtraffic&period=custom&start={}&end={}".format(
|
||||
url, start, end)
|
||||
)
|
||||
self.assertIn("averagetraffic", response["graphs"])
|
||||
|
||||
# unknown domain
|
||||
response = self.ajax_get(
|
||||
"{}?gset=mailtraffic&searchquery=unknown.com".format(url),
|
||||
status=400)
|
||||
|
||||
# check with greylist enabled
|
||||
self.set_global_parameter("greylist", True)
|
||||
response = self.ajax_get("{}?gset=mailtraffic".format(url))
|
||||
self.assertIn("averagetraffic", response["graphs"])
|
||||
|
||||
def test_account_created_graph(self):
|
||||
"""Check data."""
|
||||
self.run_update_statistics(rebuild=True)
|
||||
url = reverse("maillog:graph_list")
|
||||
response = self.ajax_get("{}?gset=accountgraphicset".format(url))
|
||||
data = (
|
||||
response["graphs"]["accountcreationgraphic"]["curves"][0]["data"])
|
||||
self.assertEqual(data[-1]["y"], 5.0)
|
||||
|
||||
def test_graphs_as_domainadmin(self):
|
||||
"""Test graph views as domain admin."""
|
||||
self.run_logparser()
|
||||
self.client.force_login(self.da)
|
||||
url = "{}?gset=mailtraffic".format(reverse("maillog:graph_list"))
|
||||
response = self.ajax_get(url)
|
||||
self.assertIn("averagetraffic", response["graphs"])
|
||||
|
||||
response = self.ajax_get("{}&searchquery=test.com".format(url))
|
||||
self.assertIn("averagetraffic", response["graphs"])
|
||||
|
||||
response = self.ajax_get(
|
||||
"{}&searchquery=test2.com".format(url), status=403)
|
||||
|
||||
def test_get_domain_list(self):
|
||||
"""Test get_domain_list view."""
|
||||
url = reverse("maillog:domain_list")
|
||||
response = self.ajax_get(url)
|
||||
self.assertIn("test.com", response)
|
||||
self.assertIn("test2.com", response)
|
||||
|
||||
|
||||
@override_settings(RRDTOOL_TEST_MODE=True)
|
||||
class ManagementCommandsTestCase(RunCommandsMixin, ModoTestCase):
|
||||
"""Management command test cases."""
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls): # noqa
|
||||
super(ManagementCommandsTestCase, cls).setUpTestData()
|
||||
admin_factories.populate_database()
|
||||
|
||||
def test_logparser(self):
|
||||
"""Test logparser command."""
|
||||
self.run_logparser()
|
||||
for d in ["global", "test.com"]:
|
||||
path = os.path.join(self.workdir, "{}.rrd".format(d))
|
||||
self.assertTrue(os.path.exists(path))
|
||||
|
||||
def test_logparser_with_greylist(self):
|
||||
"""Test logparser when greylist activated."""
|
||||
self.set_global_parameter("greylist", True)
|
||||
self.run_logparser()
|
||||
for d in ["global", "test.com"]:
|
||||
path = os.path.join(self.workdir, "{}.rrd".format(d))
|
||||
self.assertTrue(os.path.exists(path))
|
||||
|
||||
def test_update_statistics(self):
|
||||
"""Test update_statistics command."""
|
||||
self.run_update_statistics()
|
||||
path = os.path.join(self.workdir, "new_accounts.rrd")
|
||||
self.assertTrue(os.path.exists(path))
|
||||
self.run_update_statistics(rebuild=True)
|
||||
self.assertTrue(os.path.exists(path))
|
||||
@@ -0,0 +1,13 @@
|
||||
"""Stats urls."""
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = "maillog"
|
||||
|
||||
urlpatterns = [
|
||||
path("", views.index, name="fullindex"),
|
||||
path("graphs/", views.graphs, name="graph_list"),
|
||||
path("domains/", views.get_domain_list, name="domain_list"),
|
||||
]
|
||||
@@ -0,0 +1,103 @@
|
||||
# coding: utf-8
|
||||
|
||||
"""Custom views."""
|
||||
|
||||
import re
|
||||
import time
|
||||
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.contrib.auth.decorators import (
|
||||
login_required, user_passes_test, permission_required
|
||||
)
|
||||
|
||||
from modoboa.admin.models import Domain
|
||||
from modoboa.lib.exceptions import BadRequest, NotFound
|
||||
from modoboa.lib.web_utils import (
|
||||
render_to_json_response
|
||||
)
|
||||
|
||||
from . import signals
|
||||
from .lib import date_to_timestamp
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("admin.view_mailbox")
|
||||
def index(request):
|
||||
"""
|
||||
FIXME: how to select a default graph set ?
|
||||
"""
|
||||
deflocation = "graphs/?gset=mailtraffic"
|
||||
if not request.user.is_superuser:
|
||||
if not Domain.objects.get_for_admin(request.user).count():
|
||||
raise NotFound(_("No statistics available"))
|
||||
|
||||
graph_sets = {}
|
||||
for result in signals.get_graph_sets.send(
|
||||
sender="index", user=request.user):
|
||||
graph_sets.update(result[1])
|
||||
periods = [
|
||||
{"name": "day", "label": _("Day")},
|
||||
{"name": "week", "label": _("Week")},
|
||||
{"name": "month", "label": _("Month")},
|
||||
{"name": "year", "label": _("Year")},
|
||||
{"name": "custom", "label": _("Custom")}
|
||||
]
|
||||
return render(request, 'maillog/index.html', {
|
||||
"periods": periods,
|
||||
"selection": "stats",
|
||||
"deflocation": deflocation,
|
||||
"graph_sets": graph_sets
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
@user_passes_test(lambda u: u.role != "SimpleUsers")
|
||||
def graphs(request):
|
||||
gset = request.GET.get("gset", None)
|
||||
graph_sets = {}
|
||||
for result in signals.get_graph_sets.send(
|
||||
sender="index", user=request.user):
|
||||
graph_sets.update(result[1])
|
||||
if gset not in graph_sets:
|
||||
raise NotFound(_("Unknown graphic set"))
|
||||
period = request.GET.get("period", "day")
|
||||
tplvars = {"graphs": {}, "period": period}
|
||||
fname = graph_sets[gset].get_file_name(request)
|
||||
if fname is None:
|
||||
raise BadRequest(_("Unknown domain"))
|
||||
tplvars["fname"] = fname
|
||||
|
||||
if period == "custom":
|
||||
if "start" not in request.GET or "end" not in request.GET:
|
||||
raise BadRequest(_("Bad custom period"))
|
||||
start = request.GET["start"]
|
||||
end = request.GET["end"]
|
||||
expr = re.compile(r'[:\- ]')
|
||||
period_name = "%s_%s" % (expr.sub('', start), expr.sub('', end))
|
||||
start = date_to_timestamp(expr.split(start))
|
||||
end = date_to_timestamp(expr.split(end))
|
||||
else:
|
||||
end = int(time.mktime(time.localtime()))
|
||||
start = "-1%s" % period
|
||||
period_name = period
|
||||
|
||||
tplvars["domain_selector"] = graph_sets[gset].domain_selector
|
||||
tplvars["graphs"] = graph_sets[gset].export(tplvars["fname"], start, end)
|
||||
tplvars["period_name"] = period_name
|
||||
tplvars["start"] = start
|
||||
tplvars["end"] = end
|
||||
|
||||
return render_to_json_response(tplvars)
|
||||
|
||||
|
||||
@login_required
|
||||
@user_passes_test(lambda u: u.role != "SimpleUsers")
|
||||
def get_domain_list(request):
|
||||
"""Get the list of domains the user can see."""
|
||||
doms = []
|
||||
for dom in Domain.objects.get_for_admin(request.user):
|
||||
doms += [dom.name]
|
||||
doms += [alias.name for alias in dom.domainalias_set.all()]
|
||||
|
||||
return render_to_json_response(doms)
|
||||
@@ -27,6 +27,7 @@ urlpatterns = [
|
||||
path('', include("modoboa.core.urls")),
|
||||
path('admin/', include("modoboa.admin.urls")),
|
||||
path('dnstools/', include("modoboa.dnstools.urls")),
|
||||
path('stats/', include("modoboa.maillog.urls")),
|
||||
|
||||
path('user/forward/', user_views.forward, name="user_forward"),
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ chardet
|
||||
ovh
|
||||
oath
|
||||
redis
|
||||
rrdtool>=0.1.11
|
||||
|
||||
aiosmtplib
|
||||
aioredis
|
||||
|
||||
@@ -79,6 +79,7 @@ MODOBOA_APPS = (
|
||||
'modoboa.parameters',
|
||||
'modoboa.dnstools',
|
||||
'modoboa.policyd',
|
||||
'modoboa.maillog',
|
||||
# Modoboa extensions here.
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user