예제 #1
0
def email_reservation_reminders(request):
	# Exit early if the reservation reminder email template has not been customized for the organization yet.
	reservation_reminder_message = get_media_file_contents('reservation_reminder_email.html')
	reservation_warning_message = get_media_file_contents('reservation_warning_email.html')
	if not reservation_reminder_message or not reservation_warning_message:
		calendar_logger.error("Reservation reminder email couldn't be send because reservation_reminder_email.html is not defined")
		return HttpResponseNotFound('The reservation reminder email template has not been customized for your organization yet. Please visit the customization page to upload a template, then reservation reminder email notifications can be sent.')

	# Find all reservations that are two hours from now, plus or minus 5 minutes to allow for time skew.
	preparation_time = 120
	tolerance = 5
	earliest_start = timezone.now() + timedelta(minutes=preparation_time) - timedelta(minutes=tolerance)
	latest_start = timezone.now() + timedelta(minutes=preparation_time) + timedelta(minutes=tolerance)
	upcoming_reservations = Reservation.objects.filter(cancelled=False, start__gt=earliest_start, start__lt=latest_start)
	# Email a reminder to each user with an upcoming reservation.
	for reservation in upcoming_reservations:
		item = reservation.reservation_item
		item_type = reservation.reservation_item_type
		if item_type == ReservationItemType.TOOL and item.operational and not item.problematic() and item.all_resources_available()\
				or item_type == ReservationItemType.AREA and not item.required_resource_is_unavailable():
			subject = item.name + " reservation reminder"
			rendered_message = Template(reservation_reminder_message).render(Context({'reservation': reservation, 'template_color': bootstrap_primary_color('success')}))
		elif (item_type == ReservationItemType.TOOL and not item.operational) or item.required_resource_is_unavailable():
			subject = item.name + " reservation problem"
			rendered_message = Template(reservation_warning_message).render(Context({'reservation': reservation, 'template_color': bootstrap_primary_color('danger'), 'fatal_error': True}))
		else:
			subject = item.name + " reservation warning"
			rendered_message = Template(reservation_warning_message).render(Context({'reservation': reservation, 'template_color': bootstrap_primary_color('warning'), 'fatal_error': False}))
		user_office_email = get_customization('user_office_email_address')
		reservation.user.email_user(subject, rendered_message, user_office_email)
	return HttpResponse()
예제 #2
0
파일: tasks.py 프로젝트: carl-dawson/NEMO
def send_new_task_emails(request, task: Task, task_images: List[TaskImages]):
	message = get_media_file_contents('new_task_email.html')
	attachments = None
	if task_images:
		attachments = [create_email_attachment(task_image.image, task_image.image.name) for task_image in task_images]
	if message:
		dictionary = {
			'template_color': bootstrap_primary_color('danger') if task.force_shutdown else bootstrap_primary_color('warning'),
			'user': request.user,
			'task': task,
			'tool': task.tool,
			'tool_control_absolute_url': request.build_absolute_uri(task.tool.get_absolute_url())
		}
		# Send an email to the appropriate staff that a new task has been created:
		subject = ('SAFETY HAZARD: ' if task.safety_hazard else '') + task.tool.name + (' shutdown' if task.force_shutdown else ' problem')
		message = Template(message).render(Context(dictionary))
		managers = []
		if hasattr(settings, 'LAB_MANAGERS'):
			managers = settings.LAB_MANAGERS
		recipients = tuple([r for r in [task.tool.primary_owner.email, *task.tool.backup_owners.all().values_list('email', flat=True), task.tool.notification_email_address, *managers] if r])
		send_mail(subject, message, request.user.email, recipients, attachments)

	# Send an email to any user (excluding staff) with a future reservation on the tool:
	user_office_email = get_customization('user_office_email_address')
	message = get_media_file_contents('new_task_email.html')
	if user_office_email and message:
		upcoming_reservations = Reservation.objects.filter(start__gt=timezone.now(), cancelled=False, tool=task.tool, user__is_staff=False)
		for reservation in upcoming_reservations:
			if not task.tool.operational:
				subject = reservation.tool.name + " reservation problem"
				rendered_message = Template(message).render(Context({'reservation': reservation, 'template_color': bootstrap_primary_color('danger'), 'fatal_error': True}))
			else:
				subject = reservation.tool.name + " reservation warning"
				rendered_message = Template(message).render(Context({'reservation': reservation, 'template_color': bootstrap_primary_color('warning'), 'fatal_error': False}))
			reservation.user.email_user(subject, rendered_message, user_office_email)
예제 #3
0
def nanofab_rules(request):
	if request.method == 'GET':
		tutorial = get_media_file_contents('nanofab_rules_tutorial.html')
		if tutorial:
			dictionary = {
				'active_user_count': User.objects.filter(is_active=True).count(),
				'active_project_count': Project.objects.filter(active=True).count(),
			}
			tutorial = Template(tutorial).render(RequestContext(request, dictionary))
		return render(request, 'nanofab_rules.html', {'nanofab_rules_tutorial': tutorial})
	elif request.method == 'POST':
		summary = request.POST.get('making_reservations_summary', '').strip()[:3000]
		dictionary = {
			'user': request.user,
			'making_reservations_rule_summary': summary,
		}
		abuse_email = get_customization('abuse_email_address')
		email_contents = get_media_file_contents('nanofab_rules_tutorial_email.html')
		if abuse_email and email_contents:
			message = Template(email_contents, dictionary).render(Context(dictionary))
			send_mail('Laboratory rules tutorial', '', abuse_email, [abuse_email], html_message=message)
		dictionary = {
			'title': 'Laboratory rules tutorial',
			'heading': 'Tutorial complete!',
			'content': 'Tool usage and reservation privileges have been enabled on your user account.',
		}
		request.user.training_required = False
		request.user.save()
		return render(request, 'acknowledgement.html', dictionary)
예제 #4
0
def send_broadcast_email(request):
	if not get_media_file_contents('generic_email.html'):
		return HttpResponseBadRequest('Generic email template not defined. Visit the NEMO customizable_key_values page to upload a template.')
	form = EmailBroadcastForm(request.POST)
	if not form.is_valid():
		return render(request, 'email/compose_email.html', {'form': form})
	dictionary = {
		'title': form.cleaned_data['title'],
		'greeting': form.cleaned_data['greeting'],
		'contents': form.cleaned_data['contents'],
		'template_color': form.cleaned_data['color'],
	}
	content = get_media_file_contents('generic_email.html')
	content = Template(content).render(Context(dictionary))
	users = None
	audience = form.cleaned_data['audience']
	selection = form.cleaned_data['selection']
	active_choice = form.cleaned_data['only_active_users']
	try:
		if audience == 'tool':
			users = User.objects.filter(qualifications__id=selection)
		elif audience == 'project':
			users = User.objects.filter(projects__id=selection)
		elif audience == 'account':
			users = User.objects.filter(projects__account__id=selection)
		elif audience == 'all':
			users = User.objects.all()
		if active_choice:
			users.filter(is_active=True)
	except:
		dictionary = {'error': 'Your email was not sent. There was a problem finding the users to send the email to.'}
		return render(request, 'email/compose_email.html', dictionary)
	if not users:
		dictionary = {'error': 'The audience you specified is empty. You must send the email to at least one person.'}
		return render(request, 'email/compose_email.html', dictionary)
	if audience == 'tool':
		t = Tool.objects.filter(id=selection)
		subject = t[0].name + ': ' + form.cleaned_data['subject']
	else:
		subject = form.cleaned_data['subject']
	users = [x.email for x in users]
	if form.cleaned_data['copy_me']:
		users += [request.user.email]
	try:
		email = EmailMultiAlternatives(subject, from_email=request.user.email, bcc=set(users))
		email.attach_alternative(content, 'text/html')
		email.send()
	except SMTPException as e:
		dictionary = {
			'title': 'Email not sent',
			'heading': 'There was a problem sending your email',
			'content': 'NEMO was unable to send the email through the email server. The error message that NEMO received is: ' + str(e),
		}
		return render(request, 'acknowledgement.html', dictionary)
	dictionary = {
		'title': 'Email sent',
		'heading': 'Your email was sent',
	}
	return render(request, 'acknowledgement.html', dictionary)
예제 #5
0
def facility_rules(request):
    if request.method == "GET" and (request.user.training_required
                                    or request.user.access_expiration <
                                    timezone.now().date() + timedelta(weeks=2)
                                    or request.user.is_staff):
        tutorial = get_media_file_contents("facility_rules_tutorial.html")
        if tutorial:
            dictionary = {
                "active_user_count":
                User.objects.filter(is_active=True).count(),
                "active_project_count":
                Project.objects.filter(active=True).count(),
            }
            tutorial = Template(tutorial).render(
                RequestContext(request, dictionary))
        return render(request, "facility_rules.html",
                      {"facility_rules_tutorial": tutorial})
    elif request.method == "POST":
        facility_name = get_customization("facility_name")
        summary = request.POST.get("making_reservations_summary",
                                   "").strip()[:3000]
        dictionary = {
            "user": request.user,
            "making_reservations_rule_summary": summary
        }
        abuse_email = get_customization("abuse_email_address")
        email_contents = get_media_file_contents(
            "facility_rules_tutorial_email.html")
        if abuse_email and email_contents:
            message = Template(email_contents,
                               dictionary).render(Context(dictionary))
            send_mail(
                subject=f"{facility_name} rules tutorial",
                content=message,
                from_email=abuse_email,
                to=[abuse_email],
                email_category=EmailCategory.SYSTEM,
            )
        dictionary = {
            "title":
            f"{facility_name} rules tutorial",
            "heading":
            "Tutorial complete!",
            "content":
            "Tool usage and reservation privileges have been enabled on your user account.",
        }
        request.user.training_required = False
        while request.user.access_expiration < timezone.now().date(
        ) + timedelta(weeks=2):
            try:
                request.user.access_expiration = request.user.access_expiration.replace(
                    year=request.user.access_expiration.year + 1)
            except ValueError:
                request.user.access_expiration = request.user.access_expiration.replace(
                    year=request.user.access_expiration.year + 1,
                    day=request.user.access_expiration.day - 1)
        request.user.save()
        return render(request, "acknowledgement.html", dictionary)
예제 #6
0
파일: calendar.py 프로젝트: hb9kns/NEMO
def email_usage_reminders(request):
    projects_to_exclude = request.GET.getlist("projects_to_exclude[]")
    busy_users = AreaAccessRecord.objects.filter(
        end=None,
        staff_charge=None).exclude(project__id__in=projects_to_exclude)
    busy_tools = UsageEvent.objects.filter(end=None).exclude(
        project__id__in=projects_to_exclude)
    facility_name = get_customization('facility_name')
    if facility_name == '':
        facility_name = "Facility"
    # Make lists of all the things a user is logged in to.
    # We don't want to send 3 separate emails if a user is logged into three things.
    # Just send one email for all the things!
    aggregate = {}
    for access_record in busy_users:
        key = str(access_record.customer)
        aggregate[key] = {
            'email': access_record.customer.email,
            'first_name': access_record.customer.first_name,
            'resources_in_use': [str(access_record.area)],
        }
    for usage_event in busy_tools:
        key = str(usage_event.operator)
        if key in aggregate:
            aggregate[key]['resources_in_use'].append(usage_event.tool.name)
        else:
            aggregate[key] = {
                'email': usage_event.operator.email,
                'first_name': usage_event.operator.first_name,
                'resources_in_use': [usage_event.tool.name],
            }

    user_office_email = get_customization('user_office_email_address')

    message = get_media_file_contents('usage_reminder_email.html')
    if message:
        subject = f"{facility_name} usage"
        for user in aggregate.values():
            rendered_message = Template(message).render(Context({'user':
                                                                 user}))
            send_mail(subject,
                      '',
                      user_office_email, [user['email']],
                      html_message=rendered_message)

    message = get_media_file_contents('staff_charge_reminder_email.html')
    if message:
        busy_staff = StaffCharge.objects.filter(end=None)
        for staff_charge in busy_staff:
            subject = "Active staff charge since " + format_datetime(
                staff_charge.start)
            rendered_message = Template(message).render(
                Context({'staff_charge': staff_charge}))
            staff_charge.staff_member.email_user(subject, rendered_message,
                                                 user_office_email)

    return HttpResponse()
예제 #7
0
파일: alerts.py 프로젝트: hb9kns/NEMO
def send_alert_emails(alert):
    user_office_email = get_customization('user_office_email_address')
    facility_name = get_customization('facility_name')
    if facility_name == '':
        facility_name = "Facility"
    generic_email = get_media_file_contents('generic_email.html')
    if user_office_email and generic_email:
        users = User.objects.filter(is_active=True).exclude(is_staff=True)
        subject = alert.title
        title = f"{facility_name} Alert"
        color = bootstrap_primary_color('danger')
        greeting = 'Labmembers,'
        message = alert.contents
        dictionary = {
            'title': title,
            'greeting': greeting,
            'contents': message,
            'template_color': color,
        }
        msg = Template(generic_email).render(Context(dictionary))
        users = [x.email for x in users]
        email = EmailMultiAlternatives(subject,
                                       from_email=user_office_email,
                                       to=[user_office_email],
                                       bcc=set(users))
        email.attach_alternative(msg, 'text/html')
        email.send()
예제 #8
0
def compose_email(request):
    audience = request.GET.get('audience')
    selection = request.GET.get('selection')
    try:
        if audience == 'tool':
            users = User.objects.filter(
                qualifications__id=selection).distinct()
        elif audience == 'project':
            users = User.objects.filter(projects__id=selection).distinct()
        elif audience == 'account':
            users = User.objects.filter(
                projects__account__id=selection).distinct()
        else:
            dictionary = {'error': 'You specified an invalid audience'}
            return render(request, 'email/email_broadcast.html', dictionary)
    except:
        dictionary = {'error': 'You specified an invalid audience parameter'}
        return render(request, 'email/email_broadcast.html', dictionary)
    generic_email_sample = get_media_file_contents('generic_email.html')
    dictionary = {
        'audience': audience,
        'selection': selection,
        'users': users,
    }
    if generic_email_sample:
        generic_email_context = {
            'title': 'TITLE',
            'greeting': 'Greeting',
            'contents': 'Contents',
        }
        dictionary['generic_email_sample'] = Template(
            generic_email_sample).render(Context(generic_email_context))
    return render(request, 'email/compose_email.html', dictionary)
예제 #9
0
def login_user(request):
	if 'NEMO.views.authentication.RemoteUserAuthenticationBackend' in settings.AUTHENTICATION_BACKENDS or 'NEMO.views.authentication.NginxKerberosAuthorizationHeaderAuthenticationBackend' in settings.AUTHENTICATION_BACKENDS:
		if request.user.is_authenticated:
			return HttpResponseRedirect(reverse('landing'))
		else:
			return render(request, 'authorization_failed.html')

	dictionary = {
		'login_banner': get_media_file_contents('login_banner.html'),
		'user_name_or_password_incorrect': False,
	}
	if request.method == 'GET':
		return render(request, 'login.html', dictionary)
	username = request.POST.get('username', '')
	password = request.POST.get('password', '')
	user = authenticate(request, username=username, password=password)
	if user:
		login(request, user)
		try:
			next_page = request.GET[REDIRECT_FIELD_NAME]
			resolve(next_page)  # Make sure the next page is a legitimate URL for NEMO
		except:
			next_page = reverse('landing')
		return HttpResponseRedirect(next_page)
	dictionary['user_name_or_password_incorrect'] = True
	return render(request, 'login.html', dictionary)
예제 #10
0
def safety(request):
	dictionary = {}
	if request.method == 'POST':
		form = SafetyIssueCreationForm(request.user, data=request.POST)
		if form.is_valid():
			issue = form.save()
			send_safety_email_notification(request, issue)
			create_safety_notification(issue)
			dictionary = {
				'title': 'Concern received',
				'heading': 'Your safety concern was sent to NanoFab staff and will be addressed promptly',
			}
			if form.cleaned_data['post_alert']:
				now = timezone.now()
				alert_title = "Alert: Cleanroom may not be safe for entry"
				alert_preface = f'On {format_datetime(now)} {issue.reporter.get_full_name()} reported the following issue:\n'
				alert_contents = (alert_preface + issue.concern)
				safety_alert = Alert(title=alert_title, contents=alert_contents, creator=issue.reporter, debut_time=now)
				safety_alert.save()
				send_alert_emails(safety_alert)
				dictionary = {
					'title': 'Concern received',
					'heading': 'Your safety concern was sent to NanoFab staff and will be addressed promptly. An alert has been posted, and all labmembers have been emailed.',
				}
			return render(request, 'acknowledgement.html', dictionary)
	tickets = SafetyIssue.objects.filter(resolved=False).order_by('-creation_time')
	if not request.user.is_staff:
		tickets = tickets.filter(visible=True)
	dictionary['tickets'] = tickets
	dictionary['safety_introduction'] = get_media_file_contents('safety_introduction.html')
	dictionary['notifications'] = get_notifications(request.user, SafetyIssue)
	return render(request, 'safety/safety.html', dictionary)
예제 #11
0
파일: feedback.py 프로젝트: sbonaime/NEMO
def feedback(request):
    recipient = get_customization('feedback_email_address')
    email_contents = get_media_file_contents('feedback_email.html')
    if not recipient or not email_contents:
        return render(request, 'feedback.html',
                      {'customization_required': True})

    if request.method == 'GET':
        return render(request, 'feedback.html')
    contents = parse_parameter_string(request.POST, 'feedback',
                                      FEEDBACK_MAXIMUM_LENGTH)
    if contents == '':
        return render(request, 'feedback.html')
    dictionary = {
        'contents': contents,
        'user': request.user,
    }

    email = Template(email_contents).render(Context(dictionary))
    send_mail('Feedback from ' + str(request.user), email, request.user.email,
              [recipient])
    dictionary = {
        'title':
        'Feedback',
        'heading':
        'Thanks for your feedback!',
        'content':
        'Your feedback has been sent to the NanoFab staff. We will follow up with you as soon as we can.',
    }
    return render(request, 'acknowledgement.html', dictionary)
예제 #12
0
def login_user(request):
    # check to make sure we don't have a misconfiguration. pre-authentication backends need to use middleware
    response = check_pre_authentication_backends(request)
    if response:
        return response

    dictionary = {
        "login_banner": get_media_file_contents("login_banner.html"),
        "user_name_or_password_incorrect": False,
    }

    # if we are dealing with anything else than POST, send to login page
    if request.method != "POST":
        return render(request, "login.html", dictionary)
    # Otherwise try to log the user in
    else:
        username = request.POST.get("username", "")
        password = request.POST.get("password", "")
        try:
            user = authenticate(request, username=username, password=password)
        except (User.DoesNotExist, InactiveUserError):
            return authorization_failed(request)

        if user:
            login(request, user)
            try:
                next_page = request.GET[REDIRECT_FIELD_NAME]
                resolve(
                    next_page
                )  # Make sure the next page is a legitimate URL for NEMO
            except:
                next_page = reverse("landing")
            return HttpResponseRedirect(next_page)
        dictionary["user_name_or_password_incorrect"] = True
        return render(request, "login.html", dictionary)
예제 #13
0
def send_reorder_supply_reminder_email(consumable: Consumable):
	user_office_email = get_customization('user_office_email_address')
	message = get_media_file_contents('reorder_supplies_reminder_email.html')
	if user_office_email and message:
		subject = f"Time to order more {consumable.name}"
		rendered_message = Template(message).render(Context({'item': consumable}))
		send_mail(subject=subject, content=rendered_message, from_email=user_office_email, to=[consumable.reminder_email], email_category=EmailCategory.SYSTEM)
예제 #14
0
def cancel_the_reservation(reservation: Reservation, user_cancelling_reservation: User, reason: Optional[str]):
	response = check_policy_to_cancel_reservation(reservation, user_cancelling_reservation)
	# Staff must provide a reason when cancelling a reservation they do not own.
	if reservation.user != user_cancelling_reservation and not reason:
		response = HttpResponseBadRequest("You must provide a reason when cancelling someone else's reservation.")

	if response.status_code == HTTPStatus.OK:
		# All policy checks passed, so cancel the reservation.
		reservation.cancelled = True
		reservation.cancellation_time = timezone.now()
		reservation.cancelled_by = user_cancelling_reservation

		if reason:
			''' don't notify in this case since we are sending a specific email for the cancellation '''
			reservation.save()
			dictionary = {
				'staff_member': user_cancelling_reservation,
				'reservation': reservation,
				'reason': reason,
				'template_color': bootstrap_primary_color('info')
			}
			email_contents = get_media_file_contents('cancellation_email.html')
			if email_contents:
				cancellation_email = Template(email_contents).render(Context(dictionary))
				if getattr(reservation.user.preferences, 'attach_cancelled_reservation', False):
					attachment = create_ics_for_reservation(reservation, cancelled=True)
					reservation.user.email_user('Your reservation was cancelled', cancellation_email, user_cancelling_reservation.email, [attachment])
				else:
					reservation.user.email_user('Your reservation was cancelled', cancellation_email, user_cancelling_reservation.email)

		else:
			''' here the user cancelled his own reservation so notify him '''
			reservation.save_and_notify()

	return response
예제 #15
0
def email_out_of_time_reservation_notification(request):
	"""
	Out of time reservation notification for areas is when a user is still logged in a area but his reservation expired.
	"""
	# Exit early if the missed reservation email template has not been customized for the organization yet.
	if not get_media_file_contents('out_of_time_reservation_email.html'):
		return HttpResponseNotFound('The out of time reservation email template has not been customized for your organization yet. Please visit the customization page to upload a template, then out of time email notifications can be sent.')

	out_of_time_user_area = []

	# Find all logged users
	access_records:List[AreaAccessRecord] = AreaAccessRecord.objects.filter(end=None, staff_charge=None).prefetch_related('customer', 'area').only('customer', 'area')
	for access_record in access_records:
		# staff are exempt from out of time notification
		customer = access_record.customer
		area = access_record.area
		if customer.is_staff:
			continue

		if area.requires_reservation:
			# Calculate the timestamp of how late a user can be logged in after a reservation ended.
			threshold = timezone.now() if not area.logout_grace_period else timezone.now() - timedelta(minutes=area.logout_grace_period)
			threshold = datetime.replace(threshold, second=0, microsecond=0)  # Round down to the nearest minute.
			reservations = Reservation.objects.filter(cancelled=False, missed=False, shortened=False, area=area, user=customer, start__lte=timezone.now(), end=threshold)
			if reservations.exists():
				out_of_time_user_area.append(reservations[0])

	for reservation in out_of_time_user_area:
		send_out_of_time_reservation_notification(reservation)

	return HttpResponse()
예제 #16
0
def cancel_unused_reservations(request):
	# Exit early if the missed reservation email template has not been customized for the organization yet.
	if not get_media_file_contents('missed_reservation_email.html'):
		return HttpResponseNotFound('The missed reservation email template has not been customized for your organization yet. Please visit the NEMO customizable_key_values page to upload a template, then missed email notifications can be sent.')

	tools = Tool.objects.filter(visible=True, _operational=True, _missed_reservation_threshold__isnull=False)
	missed_reservations = []
	for tool in tools:
		# If a tool is in use then there's no need to look for unused reservation time.
		if tool.in_use() or tool.required_resource_is_unavailable() or tool.scheduled_outage_in_progress():
			continue
		# Calculate the timestamp of how long a user can be late for a reservation.
		threshold = (timezone.now() - timedelta(minutes=tool.missed_reservation_threshold))
		threshold = datetime.replace(threshold, second=0, microsecond=0)  # Round down to the nearest minute.
		# Find the reservations that began exactly at the threshold.
		reservation = Reservation.objects.filter(cancelled=False, missed=False, shortened=False, tool=tool, user__is_staff=False, start=threshold, end__gt=timezone.now())
		for r in reservation:
			# Staff may abandon reservations.
			if r.user.is_staff:
				continue
			# If there was no tool enable or disable event since the threshold timestamp then we assume the reservation has been missed.
			if not (UsageEvent.objects.filter(tool_id__in=tool.get_family_tool_ids(), start__gte=threshold).exists() or UsageEvent.objects.filter(tool_id__in=tool.get_family_tool_ids(), end__gte=threshold).exists()):
				# Mark the reservation as missed and notify the user & NanoFab staff.
				r.missed = True
				r.save()
				missed_reservations.append(r)

	for r in missed_reservations:
		send_missed_reservation_notification(r)

	return HttpResponse()
예제 #17
0
파일: email.py 프로젝트: bpedersen2/NEMO
def compose_email(request):
    try:
        audience = request.GET['audience']
        selection = request.GET.getlist('selection')
        no_type = request.GET.get("no_type") == "on"
        users = get_users_for_email(audience, selection, no_type)
    except:
        dictionary = {'error': 'You specified an invalid audience parameter'}
        return render(request, 'email/email_broadcast.html', dictionary)
    generic_email_sample = get_media_file_contents('generic_email.html')
    dictionary = {
        'audience': audience,
        'selection': selection,
        'no_type': no_type,
        'users': users,
    }
    if generic_email_sample:
        generic_email_context = {
            'title': 'TITLE',
            'greeting': 'Greeting',
            'contents': 'Contents',
            'template_color': '#5bc0de',
        }
        dictionary['generic_email_sample'] = Template(
            generic_email_sample).render(Context(generic_email_context))
    return render(request, 'email/compose_email.html', dictionary)
예제 #18
0
def send_missed_reservation_notification(reservation):
	subject = "Missed reservation for the " + str(reservation.tool)
	message = get_media_file_contents('missed_reservation_email.html')
	message = Template(message).render(Context({'reservation': reservation}))
	user_office_email = get_customization('user_office_email_address')
	abuse_email = get_customization('abuse_email_address')
	send_mail(subject, message, user_office_email, [reservation.user.email, abuse_email, user_office_email])
예제 #19
0
def consultation(request):
    recipient = get_customization('feedback_email_address')
    email_contents = get_media_file_contents('consultation_email.html')
    email_response_contents = get_media_file_contents(
        'consultation_email_response.html')
    if not recipient or not email_contents or not email_response_contents:
        return render(request, 'feedback.html',
                      {'customization_required': True})

    if request.method == 'GET':
        return render(request, 'consultation.html')
    contents = parse_parameter_string(request.POST, 'consultation',
                                      FEEDBACK_MAXIMUM_LENGTH)
    if contents == '':
        return render(request, 'consultation.html')
    dictionary = {
        'contents': contents,
        'user': request.user,
    }

    email = Template(email_contents).render(Context(dictionary))
    send_mail('Consultation Request from ' + str(request.user),
              '',
              request.user.email, [recipient],
              html_message=email)

    response_email = EmailMessage()
    email_body = Template(email_response_contents).render(Context(dictionary))
    storage = get_storage_class()()
    response_email.subject = 'Design Consultation Request Follow Up'
    response_email.from_email = recipient
    response_email.to = [request.user.email]
    response_email.body = email_body
    response_email.content_subtype = "html"
    response_email.attach_file(
        storage.path('design_consultation_template.pptx'))
    response_email.send()

    dictionary = {
        'title':
        'Design Consultation Request',
        'heading':
        'Request Sent!',
        'content':
        'Your design consultation request has been sent to the staff. We will follow up with you as soon as we can.',
    }
    return render(request, 'acknowledgement.html', dictionary)
예제 #20
0
def send_user_cancelled_reservation_notification(reservation: Reservation):
	if getattr(reservation.user.preferences, 'attach_cancelled_reservation', False):
		subject = "[NEMO] Cancelled Reservation for the " + str(reservation.tool)
		message = get_media_file_contents('reservation_cancelled_user_email.html')
		message = Template(message).render(Context({'reservation': reservation}))
		user_office_email = get_customization('user_office_email_address')
		attachment = create_ics_for_reservation(reservation, cancelled=True)
		reservation.user.email_user(subject, message, user_office_email, [attachment])
예제 #21
0
파일: email.py 프로젝트: krzywon/NEMO
def send_broadcast_email(request):
	content = get_media_file_contents('generic_email.html')
	if not content:
		return HttpResponseBadRequest('Generic email template not defined. Visit the customization page to upload a template.')
	form = EmailBroadcastForm(request.POST)
	if not form.is_valid():
		return render(request, 'email/compose_email.html', {'form': form})
	dictionary = {
		'title': form.cleaned_data['title'],
		'greeting': form.cleaned_data['greeting'],
		'contents': form.cleaned_data['contents'],
		'template_color': form.cleaned_data['color'],
	}
	content = Template(content).render(Context(dictionary))
	users = None
	audience = form.cleaned_data['audience']
	selection = form.cleaned_data['selection']
	active_choice = form.cleaned_data['only_active_users']
	try:
		if audience == 'tool':
			users = User.objects.filter(qualifications__id=selection)
		elif audience == 'project':
			users = User.objects.filter(projects__id=selection)
		elif audience == 'account':
			users = User.objects.filter(projects__account__id=selection)
		if active_choice:
			users = users.filter(is_active=True)
	except Exception as error:
		warning_message = 'Your email was not sent. There was a problem finding the users to send the email to.'
		dictionary = {'error': warning_message}
		logger.warning(warning_message + ' audience: {}, only_active: {}. The error message that was received is: {}'.format(audience, active_choice, str(error)))
		return render(request, 'email/compose_email.html', dictionary)
	if not users:
		dictionary = {'error': 'The audience you specified is empty. You must send the email to at least one person.'}
		return render(request, 'email/compose_email.html', dictionary)
	subject = form.cleaned_data['subject']
	users = [x.email for x in users]
	if form.cleaned_data['copy_me']:
		users += [request.user.email]
	try:
		send_mail(subject=subject, content=content, from_email=request.user.email, bcc=set(users), email_category=EmailCategory.BROADCAST_EMAIL)
	except SMTPException as error:
		site_title = get_customization('site_title')
		error_message = f"{site_title} was unable to send the email through the email server. The error message that was received is: " + str(error)
		logger.exception(error_message)
		dictionary = {
			'title': 'Email not sent',
			'heading': 'There was a problem sending your email',
			'content': error_message,
		}
		return render(request, 'acknowledgement.html', dictionary)
	dictionary = {
		'title': 'Email sent',
		'heading': 'Your email was sent',
	}
	return render(request, 'acknowledgement.html', dictionary)
예제 #22
0
def send_missed_reservation_notification(reservation):
	subject = "Missed reservation for the " + str(reservation.reservation_item)
	message = get_media_file_contents('missed_reservation_email.html')
	user_office_email = get_customization('user_office_email_address')
	abuse_email = get_customization('abuse_email_address')
	if message and user_office_email:
		message = Template(message).render(Context({'reservation': reservation}))
		send_mail(subject, message, user_office_email, [reservation.user.email, abuse_email, user_office_email])
	else:
		calendar_logger.error("Missed reservation email couldn't be send because missed_reservation_email.html or user_office_email are not defined")
예제 #23
0
def forgot_password_process(request):
	email = request.POST.get('email')
	subject = "NEMO Password Reset"
	link = ""
	try:
		user = User.objects.get(email=email)
		message = get_media_file_contents('forgot_password_email.html')
		token = ForgotPasswordToken.create(email)
		token.save()
		link = request.build_absolute_uri(reverse('password_reset_token', args=[token.hash]))
	except User.DoesNotExist:
		user = None
		message = get_media_file_contents('forgot_password_email_no_user.html')

	dictionary = {"link": link}
	rendered_message = Template(message).render(Context(dictionary))
	send_mail(subject, '', None, [email], html_message=rendered_message)

	return render(request, 'db_authentication/forgot_password_process.html', {'email': email})
예제 #24
0
파일: email.py 프로젝트: SolitonMan/NEMO
def email_broadcast(request, audience=''):
    dictionary = {
        'date_range': False,
    }
    if audience == 'tool':
        dictionary['search_base'] = Tool.objects.filter(visible=True)
    elif audience == 'project':
        dictionary['search_base'] = Project.objects.filter(active=True)
    elif audience == 'account':
        dictionary['search_base'] = Account.objects.filter(active=True)
    elif audience == 'user':
        dictionary['search_base'] = User.objects.filter(
            is_active=True).order_by('last_name', 'first_name')
    elif audience == 'group':
        dictionary['search_base'] = Group.objects.all()
    elif audience == 'tool_date':
        dictionary['search_base'] = Tool.objects.filter(visible=True)
        dictionary['date_range'] = True
    elif audience == 'project_date':
        dictionary['search_base'] = Project.objects.filter(active=True)
        dictionary['date_range'] = True
    elif audience == 'active_users_date':
        dictionary['search_base'] = User.objects.annotate(
            email_length=Length('email')).filter(is_active=True,
                                                 email_length__gt=0).order_by(
                                                     'last_name', 'first_name')
        dictionary['date_range'] = True
    elif audience == 'active_users':
        dictionary['users'] = User.objects.annotate(
            email_length=Length('email')).filter(is_active=True,
                                                 email_length__gt=0).order_by(
                                                     'last_name', 'first_name')
        dictionary['audience'] = audience
        dictionary['selection'] = None
        dictionary['cc_users'] = User.objects.filter(is_active=True).order_by(
            'last_name', 'first_name')
        dictionary['date_range'] = False
        dictionary['start'] = None
        dictionary['end'] = None
        dictionary['current_time'] = timezone.now()

        generic_email_sample = get_media_file_contents('generic_email.html')
        if generic_email_sample:
            generic_email_context = {
                'title': 'TITLE',
                'greeting': 'Greeting',
                'contents': 'Contents',
            }
            dictionary['generic_email_sample'] = Template(
                generic_email_sample).render(Context(generic_email_context))

        return render(request, 'email/compose_email.html', dictionary)

    dictionary['audience'] = audience
    return render(request, 'email/email_broadcast.html', dictionary)
예제 #25
0
def send_out_of_time_reservation_notification(reservation:Reservation):
	subject = "Out of time in the " + str(reservation.area.name)
	message = get_media_file_contents('out_of_time_reservation_email.html')
	user_office_email = get_customization('user_office_email_address')
	if message and user_office_email:
		message = Template(message).render(Context({'reservation': reservation}))
		recipients = [reservation.user.email]
		recipients.extend(reservation.area.abuse_email_list())
		send_mail(subject, message, user_office_email, recipients)
	else:
		calendar_logger.error("Out of time reservation email couldn't be send because out_of_time_reservation_email.html or user_office_email are not defined")
예제 #26
0
def send_tool_usage_counter_email(counter: ToolUsageCounter):
    user_office_email = get_customization('user_office_email_address')
    message = get_media_file_contents('counter_threshold_reached_email.html')
    if user_office_email and message:
        subject = f"Warning threshold reached for {counter.tool.name} {counter.name} counter"
        rendered_message = Template(message).render(
            Context({'counter': counter}))
        send_mail(subject=subject,
                  content=rendered_message,
                  from_email=user_office_email,
                  to=counter.warning_email,
                  email_category=EmailCategory.SYSTEM)
예제 #27
0
def set_task_status(request, task, status_name, user):

    if not user.is_staff and status_name:
        raise ValueError("Only staff can set task status")

        #If no status is given, assign to default status. This will make sure all tasks have a proper Task History
    if not status_name:
        status_name = "default"

    status = TaskStatus.objects.get_or_create(name=status_name)
    TaskHistory.objects.create(task=task,
                               status=status_name,
                               user=user,
                               shutdown=task.force_shutdown)

    status_message = f'On {format_datetime(timezone.now())}, {user.get_full_name()} set the status of this task to "{status_name}".'
    task.progress_description = status_message if task.progress_description is None else task.progress_description + '\n\n' + status_message
    task.save()

    message = get_media_file_contents('task_status_notification.html')
    # Send an email to the appropriate staff that a task status has been updated:
    if message:
        dictionary = {
            'template_color':
            bootstrap_primary_color('success'),
            'title':
            f'{task.tool} task notification',
            'status_message':
            status_message,
            'notification_message':
            status.notification_message,
            'task':
            task,
            'tool_control_absolute_url':
            request.build_absolute_uri(task.tool.get_absolute_url())
        }
        subject = f'{task.tool} task notification'
        message = Template(message).render(Context(dictionary))
        recipients = [
            task.tool.primary_tool_owner.email
            if status.notify_primary_tool_owner else None,
            task.tool.notification_email_address
            if status.notify_tool_notification_email else None,
            status.custom_notification_email_address
        ]
        if status.notify_backup_tool_owners:
            recipients += task.tool.backup_tool_owners.values_list('email')
        recipients = filter(None, recipients)
        send_mail(subject=subject,
                  content=message,
                  from_email=user.email,
                  to=recipients,
                  email_category=EmailCategory.TASKS)
예제 #28
0
def send_safety_email_notification(request, issue):
	recipient = get_customization('safety_email_address')
	message = get_media_file_contents('safety_issue_email.html')
	if recipient and message:
		subject = 'Safety issue'
		dictionary = {
			'issue': issue,
			'issue_absolute_url': request.build_absolute_uri(issue.get_absolute_url()),
		}
		rendered_message = Template(message).render(Context(dictionary))
		from_email = issue.reporter.email if issue.reporter else recipient
		send_mail(subject=subject, content=rendered_message, from_email=from_email, to=[recipient], email_category=EmailCategory.SAFETY)
예제 #29
0
파일: email.py 프로젝트: dsbarth/NEMO
def compose_email(request):
    audience = request.GET.get('audience')
    selection = request.GET.get('selection')
    try:
        if audience == 'tool':
            users = User.objects.filter(
                qualifications__id=selection).distinct()
        elif request.user.is_staff:
            if audience == 'project':
                users = User.objects.filter(projects__id=selection).distinct()
            elif audience == 'account':
                users = User.objects.filter(
                    projects__account__id=selection).distinct()
            elif audience == 'area':
                access_levels = Area.objects.get(
                    pk=selection).get_physical_access_levels()
                user_filter = Q(physical_access_levels__in=access_levels)
                # if one of the access levels allows staff, add all staff
                if access_levels.filter(allow_staff_access=True).exists():
                    user_filter = user_filter | Q(is_staff=True)
                users = User.objects.filter(user_filter).distinct()
            elif audience == 'all':
                users = User.objects.all()
            else:
                dictionary = {'error': 'You specified an invalid audience'}
                return render(request, 'email/email_broadcast.html',
                              dictionary)
        else:
            dictionary = {
                'error': 'You may not broadcast email to this audience'
            }
            return render(request, 'email/email_broadcast.html', dictionary)
    except:
        dictionary = {'error': 'You specified an invalid audience parameter'}
        return render(request, 'email/email_broadcast.html', dictionary)

    generic_email_sample = get_media_file_contents('generic_email.html')
    dictionary = {
        'audience': audience,
        'selection': selection,
        'users': users,
    }
    if generic_email_sample:
        generic_email_context = {
            'title': 'TITLE',
            'greeting': 'Greeting',
            'contents': 'Contents',
            'template_color': '#5bc0de',
        }
        dictionary['generic_email_sample'] = Template(
            generic_email_sample).render(Context(generic_email_context))
    return render(request, 'email/compose_email.html', dictionary)
예제 #30
0
def send_safety_email_notification(request, issue):
	subject = 'Safety issue'
	dictionary = {
		'issue': issue,
		'issue_absolute_url': request.build_absolute_uri(issue.get_absolute_url()),
	}
	recipient = get_customization('safety_email_address')
	message = get_media_file_contents('safety_issue_email.html')
	if not recipient or not message:
		return
	rendered_message = Template(message).render(Context(dictionary))
	from_email = issue.reporter.email if issue.reporter else recipient
	send_mail(subject, '', from_email, [recipient], html_message=rendered_message)