def prepare_email_report(new_items_dict, user):
    """Using new_items_dict, builds an HTML-tree report to send,
    and returns HTML-as-string and stripped of tags HTML (text)."""

    html = (
        E.html(
            E.body(
                E.h3('Library Renewal script report', style='font-family: Helvetica, arial, sans-serif;'),
                E.p(E.strong('Account Name: '), user['name'], style='font: 13px Helvetica, arial, sans-serif;'),
                E.p('The library renewal script has renewed, or attempted to renew items for you. A report listing items that were renewed as well as those that could not be renewed is below.', style='font: 13px Helvetica, arial, sans-serif;'),
                E.p('If you notice any strange behaviour, or have questions about this script, please contact David Lane at ', E.a('*****@*****.**', href="mailto:[email protected]?Subject=Library%20Renewal%20Script", target="_top"), '.', style='font: 13px Helvetica, arial, sans-serif;'),
                E.h2('Renewed:', style='color: green; font-family: Helvetica, arial, sans-serif;'),
                E.table(
                    E.tr(
                        E.th('Title', style='padding: 0.5rem; background-color: #ddd;'),
                        E.th('Author', style='padding: 0.5rem; background-color: #ddd;'),
                        E.th('Renewals', style='padding: 0.5rem; background-color: #ddd;'),
                        E.th('Due date', style='padding: 0.5rem; background-color: #ddd;'),
                        E.th('Error', style='padding: 0.5rem; background-color: #ddd;')
                        ),
                    style='border-collapse: collapse; font-size: inherit; font: 13px Helvetica, arial, sans-serif; text-align: left;'),
                E.h2('Could not be renewed:', style='color: firebrick; font-family: Helvetica, arial, sans-serif;'),
                E.table(
                    E.tr(
                        E.th('Title', style='padding: 0.5rem; background-color: #ddd;'),
                        E.th('Author', style='padding: 0.5rem; background-color: #ddd;'),
                        E.th('Renewals', style='padding: 0.5rem; background-color: #ddd;'),
                        E.th('Due date', style='padding: 0.5rem; background-color: #ddd;'),
                        E.th('Error', style='padding: 0.5rem; background-color: #ddd;')
                        ),
                    style='border-collapse: collapse; font-size: inherit; font: 13px Helvetica, arial, sans-serif; text-align: left;')
                )))
    
    renewed_table = html.findall('.//table')[0]
    not_renewed_table = html.findall('.//table')[1]

    for item in new_items_dict:
        error = new_items_dict[item].get('error')
        if error is None:
            error = ''

        item_tree = (E.tr(
            E.td(new_items_dict[item]['title'], style='padding: 0.5rem;'),
            E.td(new_items_dict[item]['author'], style='padding: 0.5rem;'),
            E.td('{0!s}'.format(new_items_dict[item]['renewals']), style='padding: 0.5rem;'),
            E.td(new_items_dict[item]['due_date'], style='padding: 0.5rem;'),
            E.td(error, style='padding: 0.5rem;'),
            ))
        if new_items_dict[item].get('renewed') is True:
            # Add an entry to the renewed table
            renewed_table.append(item_tree)
        elif new_items_dict[item].get('renewed') is False:
            # Add to the could-not-renew table
            not_renewed_table.append(item_tree)
        elif new_items_dict[item].get('error') is not None:
            # also add to the could-not-renew table
            not_renewed_table.append(item_tree)

    return etree.tostring(html), strip_tags(etree.tostring(html, pretty_print=True))
def gen_html(title, alignment, alignment_IDs, additional_data_fields=[], aa_css_class_list=None, sections={}):
    '''
    additional_data_fields structure: [ { [PDB_ID]_[PDB_CHAIN_ID] : data }, { [PDB_ID]_[PDB_CHAIN_ID] : data }, ... ] with a separate dict for each data type, and where data is of len(alignment). Column headers not required.
    aa_css_class_list can be used to override the CSS classes assigned to each residue. Should be given as a list of lists, with shape: (len(alignment), len(alignment[0])).
    sections structure: {int(position): [section_title, additional_field_header1, additional_field_header2, ...]}
    '''
    output_html_tree = E.html(
        E.head(
            E.link()
        ),
        E.body(
            E.h2(title),
            E.table()
        )
    )

    link = output_html_tree.find('head/link')
    link.set('type', 'text/css')
    link.set('href', 'seqlib.css')
    link.set('rel', 'stylesheet')
    html_body = output_html_tree.find('body')
    html_table = html_body.find('table')

    for i in range(len(alignment)):
        if i in sections:
            #html_table.append( E.tr( E.td( E.div( E.strong(E.u(sections[i])) ), nowrap='' ) ) )
            tr = etree.SubElement(html_table, 'tr')
            for col in range(len(sections[i])):
                tr.append( E.td( E.div( E.strong(E.u(sections[i][col])) ), nowrap='' ) )
        # row
        row = E.tr()

        # alignment ID div
        row.append( E.td( E.div( str(alignment_IDs[i]) ,CLASS='ali') ) )

        # add any additional data fields (also in divs)
        for d in range(len(additional_data_fields)):
            data = additional_data_fields[d][alignment_IDs[i]]
            if data != None:
                row.append( E.td( E.div(data, CLASS='ali'), nowrap='') )
            else:
                row.append( E.td( E.div('', CLASS='ali'), nowrap='') )

        # format sequence with css classes. Returned as a list of span objects
        if aa_css_class_list != None:
            if aa_css_class_list[i] != None:
                prettyseq = targetexplorer.core.seq2pretty_html(alignment[i], aa_css_class_list=aa_css_class_list[i])
            else:
                prettyseq = targetexplorer.core.seq2pretty_html(alignment[i])
        else:
            prettyseq = targetexplorer.core.seq2pretty_html(alignment[i])

        # set up sequence div
        seq_div = E.div(id='sequence',CLASS='ali')
        seq_div.set('style','background-color:#dddddd;letter-spacing:-5px')

        # add sequence to div
        for span in prettyseq:
            seq_div.append(span)

        row.append( E.td( seq_div, nowrap='' ) )

        # add the row to the table
        html_table.append(row)

    return output_html_tree