def construct_email(cfg, query, location, posts):
    """Construct an email message.

    Args:
        cfg: email configuration.
        query: search term used.
        location: location to search for jobs.
        posts: dictionary containing new job listings.

    Returns:
        message: string containing the email message.
    """
    nposts = len(posts)

    # unpack required variables
    user, send_to = cfg['email_from'], cfg['email_to']

    # unpack optional variables
    try:
        name = cfg['name']
    except KeyError:
        # if the `name` key isn't present, then use the first part of the
        # email address to address recipient.
        name = cfg['email_to'].split('@')[0]

    try:
        sender_name = cfg['sender_name']
    except KeyError:
        sender_name = cfg['email_from']

    try:
        signature = cfg['signature']
    except KeyError:
        signature = ''

    # some temporary variables to correct grammar in the email message
    was_were = 'was' if nposts == 1 else 'were'
    is_are = 'is' if nposts == 1 else 'are'
    job_s = 'job' if nposts == 1 else 'jobs'
    listing_s = 'listing' if nposts == 1 else 'listings'

    subject = f'Job opportunities: {nposts} new {job_s} posted'
    description = '{}. {jobtitle} @ {company}\nLink: {url}\nLocation: {location}\nSnippet: {desc}\n'
    posts_content = '\n'.join(description.format(i+1, **p) for i, p in enumerate(posts.values()))

    s = (
        f'From: {sender_name} <{user}>\n'
        f'To: {send_to}\n'
        f'Subject: {subject}\n'
        f'Hello {name},\n\n'
        f'There {is_are} {nposts} new job {listing_s} to review.\n'
        f'The following job {listing_s} {was_were} found for {repr(query)} in {repr(location)}:\n\n'
        f'{posts_content}\n'
        f'{signature}'
    )

    return s