diff --git a/setup.py b/setup.py
index 02ec65745c40c2c46d18cdb87fcea26bf5459c8d..31a1862fab536df51dcf722d8bb5b3367d5a8024 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
 
 setup(
     name='ticdesk',
-    version='0.11',
+    version='0.12',
     packages=find_packages(),
     include_package_data=True,
     author='Teckids e.V.',
diff --git a/ticdesk/settings.py b/ticdesk/settings.py
index 4e3cca5f441fd9544737107a6d38079e631b33d9..b225e92809952743d830dd5d92bb381b317131ec 100644
--- a/ticdesk/settings.py
+++ b/ticdesk/settings.py
@@ -60,6 +60,7 @@ MIDDLEWARE = [
 CRON_CLASSES = [
     'ticdesk_account.cron.CleanGroups',
     'ticdesk_account.cron.CleanPersons',
+    'ticdesk_account.cron.BirthdayMails',
 ]
 
 ROOT_URLCONF = 'ticdesk.urls'
diff --git a/ticdesk_account/cron.py b/ticdesk_account/cron.py
index 485385bef13f6bbc36f28515ebd807a8359dcace..d11434e4eb9f7330da4c3bb964cb28395e6ca904 100644
--- a/ticdesk_account/cron.py
+++ b/ticdesk_account/cron.py
@@ -1,7 +1,12 @@
+from datetime import date, timedelta
+
+from django.core.mail import EmailMessage
+from django.utils.translation import ugettext_lazy as _
 from django_cron import CronJobBase, Schedule
 from ldap import INVALID_SYNTAX
 
 from .models import TeckidsGroup, TeckidsPerson
+from ticdesk_org.util import may_see_person
 
 class CleanGroups(CronJobBase):
     RUN_EVERY_MINS = 5
@@ -38,3 +43,40 @@ class CleanPersons(CronJobBase):
             except INVALID_SYNTAX:
                 # Uncritical because we probably hit a no-op
                 pass
+
+class BirthdayMails(CronJobBase):
+    RUN_EVERY_MINS = 1440
+
+    schedule = Schedule(run_every_mins=RUN_EVERY_MINS)
+    code = 'ticdesk_account.birthday_mails'
+
+    def do(self):
+        # Get persons who subscribed to birthday mails
+        persons = TeckidsPerson.objects.filter(setting_birthday_mail_days__gte=1).all()
+
+        for person in persons:
+            today = date.today()
+            last = today + timedelta(days=person.setting_birthday_mail_days)
+
+            # Get persons who have their birthday in that period
+            birthday_persons = []
+            for delta in range(0, person.setting_birthday_mail_days + 1):
+                day = today + timedelta(days=delta)
+                birthday_persons += TeckidsPerson.objects.filter(
+                    date_of_birth_str__endswith=day.strftime('%m-%d')
+                ).order_by('date_of_birth_str').all()
+
+            # Iterate over persons and check read access
+            matching_persons = [birthday_person for birthday_person in birthday_persons if may_see_person(birthday_person, person)]
+
+            if matching_persons:
+                # Generate mail
+                message = EmailMessage()
+                message.to = [person.mail]
+                message.subject = _('Geburtstage von %s bis %s') % (str(today), str(last))
+                message.body = _('Hallo %s,\n\ndie folgenden Personen haben in nächster Zeit Geburtstag:\n\n') % person.given_name
+                for birthday_person in matching_persons:
+                    message.body += _('%s\t%s (%s Jahre)\n') % (str(birthday_person.date_of_birth),
+                        birthday_person.cn, str(birthday_person.age_at(last))
+                    )
+                message.send()
diff --git a/ticdesk_account/models.py b/ticdesk_account/models.py
index bd6180cd39bf6495a0247c3dfb5c185e2f84a5c7..68aa0dedf56265e2aa715167c4f4bf2c3ff5d188 100644
--- a/ticdesk_account/models.py
+++ b/ticdesk_account/models.py
@@ -176,6 +176,7 @@ class TeckidsPerson(ldapdb.models.Model, TeckidsLdapMixin):
     home_phone = CharField(db_column='homePhone', max_length=20, verbose_name=_('Telefon (Festnetz privat)'))
     mobile = CharField(db_column='mobile', max_length=20, verbose_name=_('Handy'))
     date_of_birth = DateField(db_column='dateOfBirth', verbose_name=_('Geburtsdatum'))
+    date_of_birth_str = CharField(db_column='dateOfBirth', max_length=10)
     jpeg_photo = ImageField(db_column='jpegPhoto')
 
     # Location
@@ -216,6 +217,11 @@ class TeckidsPerson(ldapdb.models.Model, TeckidsLdapMixin):
     # Group membership
     member_of = ListField(db_column='memberOf')
 
+    # Settings
+    setting_birthday_mail_days = IntegerField(db_column='teckidsSettingsBirthdayMailDays',
+        default=0, verbose_name=_('Geburtstags-E-Mail-Tage')
+    )
+
     def clean(self):
         # Set default cn if not given
         if not self.cn:
diff --git a/ticdesk_org/util.py b/ticdesk_org/util.py
index 865adf8d3cb7d46e7afa19ff6355576bd3d2335a..d8101126ad1cd86862903b81d8104dd77c15a074 100644
--- a/ticdesk_org/util.py
+++ b/ticdesk_org/util.py
@@ -45,12 +45,13 @@ def may_see_group(group, user):
     return False
 
 def may_see_person(person, user):
-    # Not logged-in users cannot see anything
-    if not user.is_authenticated:
-        return False
+    if not isinstance(user, TeckidsPerson):
+        # Not logged-in users cannot see anything
+        if not user.is_authenticated:
+            return False
 
-    # Replace user variable with the user's TeckidsPerson
-    user = TeckidsPerson.objects.get(uid=user.username)
+        # Replace user variable with the user's TeckidsPerson
+        user = TeckidsPerson.objects.get(uid=user.username)
 
     # Everyone can see themselves
     if user == person: