HNHacker News
TopNewBestAskShowJobs

iam-TJ

1,507 karma · joined February 23, 2016

submissionscomments
iam-TJ··on Git making me want to pull my hair out yet again

  git reset --soft HEAD^
  # make changes so index only contains what you want
  git commit -a -C ORIG_HEAD
of if you prefer:

  git config --global alias.undo reset --soft HEAD^
  git config --global alias.redo commit -a -C ORIG_HEAD
then:

  git undo
  # make changes so index only contains what you want
  git redo
You could use -c (--reedit-message=) instead of -C (--reuse-message=) for further flexibility.

ORIG_HEAD is set to point to the most recent HEAD when using reset. See "man git-reset" > EXAMPLES > "Undo a commit and redo".

iam-TJ··on Foreigners can remotely open business in Ukraine and pay taxes here
This is a great way to express support for Ukraine. It is also aimed initially at foreign IT businesses. A much better, earlier, overview of the extent of the aims and opportunities are found at "Government green lights e-residency in Ukraine" [0]

""During a full-scale war, it is very important to attract additional funds to the budget and support the country's economy. The e-resident status will allow foreigners to register a business in a few clicks, develop it remotely and pay taxes in Ukraine on favorable terms (5% of income, 15% of the amount, which exceeds the limit)", said the minister.

According to Fedorov, the Ministry of Digitization team is already working on the development of a web version and a mobile application using digital signature cloud technologies. This will allow entrepreneurs to register or open a bank account quickly and conveniently, through a browser or smartphone, without papers and complex bureaucratic procedures"

[0] https://www.kmu.gov.ua/en/news/uryad-pidtrimav-zaprovadzhenn...

iam-TJ··on Crazy Thin ‘Deep Insert’ ATM Skimmers
No connectivity for the retailer's device, not for the customer device.

There are also quite a few payment terminals that still do dial-on-demand to get authorisation from the merchant service provider (Chip&PIN/NFC Contactless).

I still see those in the UK especially at independent fuel stations. The additional delay waiting for the terminal to dial and connect sometimes makes me think it has failed - had a few occasions where the line was busy and the terminal redialled several times before it finally made it!

iam-TJ··on Ask HN: How do I write a Linux driver for my 15 year old photo printer?
Lots of great advice here along the lines of "is it really worth your time and energy", but if you really want to tackle it don't focus on the hardware, focus on the existing (proprietary) software, and wrap it with your own libraries to observe and record inputs and outputs.

  lp myfile -> input-wrapper -> proprietary-library -> system-library -> printer
                          |                             |
                          ---------floss-library---------

As the existing driver is 32-bit there are two options for debugging on a x86_64 platform:

1. A 32-bit virtual-machine install with the printer connected via USB pass-through so the existing driver correctly operates the printer

2. As someone else said, use qemu-system-i386 with a 32-bit chroot minimal install

Look at the source-code of the binary package containing the driver. Identify the proprietary binary blobs (most likely shared libraries) that are included.

Use tools like objdump to identify the names of external functions they import from system libraries (which they'll call), and the functions they export for other tools to call into.

Create basic wrapper libraries with the same names as the system libraries that export the same function names and signatures as the system library.

Have those functions in your wrapper libraries call the same functions in the system libraries and pass through the arguments untouched BUT also have your wrapper functions log/dump/record the function and arguments being passed.

In the same way create wrapper libraries that have the same name as the proprietary blob libraries and export the same functions. Have these functions call into the proprietary libraries and pass arguments untouched, and log/dump/record in the same way.

Use LD_LIBRARY_PATH to have your wrapper libraries loaded and used by the tool used to print - I'd recommend using something basic like "lp".

Do basic text printing to begin with and observe what the proprietary libraries output to the printer in response.

You'll likely see control codes to configure the printer and then possibly the actual ASCII codes of the text unless the driver converts everything to bitmaps before sending. Even then, by printing one character at a time it is usually possibly to determine the data format of bitmaps and the positioning data.

Compare with existing open-source drivers for similar devices from the same manufacturer since there is likely to be a lot of overlap and shared technology/code.

Once you think you've got a handle on it have your wrapper library that pretends to be the proprietary library bypass the proprietary library and directly format and send the data to the system libraries.

As you figure out more of the data format put that into your replacement FLOSS library until the proprietary is no longer required. At that point you can build the FLOSS library for 64-bit and upstream it for everyone to enjoy.

Or just buy a replacement printer that is well supported already!

iam-TJ··on Show HN: StackAid – Fund all your open-source dependencies
Have you already considered working with/integrating with SPI [0] (Software In The Public Interest) that acts as legal and financial steward for many projects from large to small (e.g. Debian, NTPsec) ?

[0] https://www.spi-inc.org/projects/

iam-TJ··on Why companies are interested in Myers-Briggs types
I think it may be you feeling overly cynical.

I was using this style of enquiry with new hires 20+ years ago as a natural step to ensure we would get the best out of them - it just seemed like an obvious thing to do.

I don't like sticking square pegs in round holes so if by understanding, and being able to accommodate, personal characteristics, we can make the person more comfortable they'll generally contribute more, faster, and better.

You hate travelling in rush-hour? fine, set your own hours to fit in with the team requirements.

E.g. for myself I'd say: "No distractions - if I'm obviously focused on something do NOT disturb me - send an email" and "I'm productive when my brain gets intensely into something - when it doesn't I don't sit around I go do something else" and "I work better in darkness or dim light, or overnight" and "Sometimes I need to do intense random brain-storming sessions to clear the crap out my head".

iam-TJ··on Ask HN: 2FA for Credit Cards?
There is. Strong Customer Authentication

https://en.wikipedia.org/wiki/3-D_Secure

https://www.mastercard.com/gateway/payment-solutions/securit...

https://www.visa.co.uk/partner-with-us/payment-technology/st...

https://www.barclaycard.co.uk/business/business-matters/frau...

iam-TJ··on Ask HN: Static site generator that can cope with octopus juggling geysers?
Thanks - that may be a way to deal with my hybrid requirements; I have to make the solution work with a 30 year legacy of existing pages that make use of apache functionality in various ways.

Whatever I do has to apply incrementally as I (slowly) transfer everything into the new SSG controlled repository.

Normalised is definitely where I want to be for the canonical representation.

I guess there'd be two canonical representations actually; the SSG 'source' and the normalised hybrid HTML+SSI.

iam-TJ··on Ask HN: Static site generator that can cope with octopus juggling geysers?
Thanks; transclusion is a good descriptive word for it although hard to grok until you read the explanation!

Multimarkdown sounds rather like pandoc which I use in other contexts.

iam-TJ··on Ask HN: Static site generator that can cope with octopus juggling geysers?
I dumped PHP around 2005 :)
iam-TJ··on Ask HN: Static site generator that can cope with octopus juggling geysers?
Yes; initially that was what I was, and still am, considering.

I hesitate because some of my existing content uses mod-include and other apache httpd functionality in different ways for different purposes.

I considered segmenting the site so some parts are cached/proxied using SSR (Server Side Rendering for those that wonder) but then I'm introducing artificial barriers that in the future I may forget are there and trip over whilst trying to throw some quick PoC or demo up.

iam-TJ··on Ask HN: Static site generator that can cope with octopus juggling geysers?
De-duplication, or rather, not duplicating in the first place. Perfectionist requirement :)
iam-TJ··on Ask HN: Static site generator that can cope with octopus juggling geysers?
Yes and No. The very limited functionality of mod-include and apache httpd expr-essions isn't Turing-complete and cannot be manipulated by client requests.

Secondly, as these are tightly integrated into httpd it turns out to be extremely efficient. I've been using mod-include in many ways for about 20 years.

Only files marked with execute attribute (+x) are handled by mod-include in my case.

iam-TJ··on Ask HN: Static site generator that can cope with octopus juggling geysers?
How does this avoid the nesting bug? There are actually two bugs currently for my use-case:

1. The existing one where the code intended to detect nested includes fails to detect it

2. No way to know if nesting is happening, what level, or how many (that's the code I've added to mod_include)

iam-TJ··on Ask HN: Static site generator that can cope with octopus juggling geysers?
The point here is NOT to have the site-generator (SSG) create complete index/overview pages that would then include all the titles+summaries, but instead to understand a <!--#include ...>, parse the document it points to, and be able to use the metadata for generating its indexes, tag clouds, or whatever BUT not include the document itself.

So the SSG will understand and use the per-page metadata to generate index-type pages but actual inclusion of content is delayed until it is requested from the web-server.

Because I have covered a huge number of categories over the years and many pages will be included in multiple indexes/overviews/tag-clouds, I do not want multiple index pages with copies of the same text.

iam-TJ··on Outlook.com is silently discarding email messages (2015)
If I recall correctly didn't Yahoo used to provide the BTinternet.com email service? I seem to remember some announcements about BT eventually moving off it but not sure if the backend MTAs changed.

https://home.bt.com/pages/email/index2.html

iam-TJ··on We clone a running VM in 2 seconds
You know I'm not sure... TCP is stream oriented and supposed to handle lost packets so I'd think the TCP layer itself would handle the pause. If the sender doesn't get an ACK for a packet then it'll resend that packet later (TCP has sequence numbers so the stream can be reconstructed from out-of-order delivery and resends).

I revisited my proof-of-concept test scripts when I wrote the previous comment. I'll try in the next week to add some additional tests in there to determine stream reliability and packet delay/loss.

UDP of course doesn't have the same benefits.

I'm using ECMP + Anycast in a project I've been developing for the last couple of years (K18S or Keep It Simples Stupids) to effectively replace Kubernetes functionality with standard protocols and tooling that is in almost all distros.

We started out with the challenge of replacing the major parts of CNIs and that is where the ECMP + Anycast work arose from.

Native IPv6 with only VLANs and direct routing (no messing about with IPv4, NAT or overlay networks), ECMP + Anycast gives load-balanced routing to pods with automatic detection of lost hosts. Pods exposed to public get public IPv6 address in addition to a ULA (Unique Local Address, formerly called site-local). ULAs used for private routing.

Systemd-networkd is configured automatically by systemd-nspawn so there doesn't need to be a massive, foreign, orchestration control system.

Systemd-nspawn/systemd-machined to manage container lifecycles with OCI compliant images, or leverage nspawn's support for overlayfs to build machine images from several different file-system images. (rather like Docker's layers but always separate, not combined) but can be used in a pick-and-mix fashion to assemble a container that has several related but separately packaged components.

Configs for /etc/ of each container mapped in from external storage using the same overlayfs method. In most cases everything is read-only but some hosts/pods can be allowed to write into the /etc/ overlay and those changes can be optionally committed to the external storage.

Adopting IPV6 and dropping IPv4 was the best thing we ever did in terms of keeping things simple and straightforward and relying on the existing network protocols and layers, instead of re-inventing it all (badly).

At the time we started Kubernetes didn't even have IPv6 support and even once it did many CNIs couldn't handle it properly.

iam-TJ··on After self-hosting my email for twenty-three years I have thrown in the towel
I've been hosting and operating my own MTA MX with Postfix since 2005. I have Postfix set to use "MailDir" format storage (one file per email) and then use Procmail filters to direct emails into per-sender or per-topic specific folders when they arrive on the server - nothing needed to be done in the email client. Dovecot provides the IMAP4 client interface. Thunderbird connects via IMAP4.

Each domain has its own user home directory so for each there is a /home/${domain_name}/Maildir/ directory as the base for storing emails, and each IMAP4 folder has an associated directory. Snippet:

  $ ls -1da  Maildir/.Technology.FOSS.Projects.Linux*
  Maildir/.Technology.FOSS.Projects.Linux
  Maildir/.Technology.FOSS.Projects.LinuxContainers
  Maildir/.Technology.FOSS.Projects.Linux.drbd
  Maildir/.Technology.FOSS.Projects.Linux.kernel
  Maildir/.Technology.FOSS.Projects.Linux.linaro.dev
  Maildir/.Technology.FOSS.Projects.Linux.linux-i2c
  Maildir/.Technology.FOSS.Projects.Linux.linux-input
  Maildir/.Technology.FOSS.Projects.Linux.linux-pci
  Maildir/.Technology.FOSS.Projects.Linux.linux-usb
Here's an extended snippet example from $HOME/.procmailrc that directs deliveries into the correct directory (IMAP4 folder):

  :0H
  * ^List-id: .*linux-usb\.vger\.kernel\.org
  $HOME/Maildir/.Technology.FOSS.Projects.Linux.linux-usb/
  
  :0H
  * ^List-id: .*linux-wireless\.vger\.kernel\.org
  $HOME/Maildir/.Technology.FOSS.Projects.Linux.linux-wireless/
  
  :0H
  * ^List-id: .*yaffs\.lists\.aleph1\.co\.uk
  $HOME/Maildir/.Technology.FOSS.Projects.Linux.yaffs/

  :0H
  * ^List-id: .*util-linux\.vger\.kernel\.org
  $HOME/Maildir/.Technology.FOSS.Projects.Linux.util-linux/


  ### LinuxContainers
  :0H
  * ^List-id: .*lxc-devel\.lists\.linuxcontainers\.org
  $HOME/Maildir/.Technology.FOSS.Projects.LinuxContainers/

  ### Linaro
  
  :0H
  * ^List-id:.*linaro-dev\.lists\.linaro\.org
  $HOME/Maildir/.Technology.FOSS.Projects.Linux.linaro.dev/

  :0H
  * ^List-id:.*linaro-kernel\.lists\.linaro\.org
  $HOME/Maildir/.Technology.FOSS.Projects.Linux.linaro.kernel/
iam-TJ··on Show HN: I'm building an open-source Amazon
The kind of arguments you raise here have always, to me, basically looked like:

"I want something for nothing"

Or in more detail:

"I want to take something you created and agreed to share with me (on the proviso I like-wise share any changes as an exchange of value). I deem your software valuable to me but I won't be paying you money for it. I'll add something else to it so it fits my use-case. But, I refuse/object to sharing my changes because they're valuable."

iam-TJ··on We clone a running VM in 2 seconds
Have you considered, or tested, using ECMP (Equal Cost Multiple Path routing) and anycast for that?

I did some extensive IPv4 and IPv6 ECMP anycast testing a couple years ago where we'd randomly bring up and kill hosts and containers.

The network layer provided the fault tolerance and could be tweaked to react very quickly to missing hosts.

iam-TJ··on Falsehoods programmers believe about email
In respect of handling email addresses provided by customers (note I do not use what I consider has become almost a derogatory term "users") the U.K. Government Digital Service (GDS) guidelines on interface/experience design and implementation patterns is widely seen as the gold standard[3]. Here's what they have to say about accepting email addresses[0] including code examples:

    When asking users for their email address, you must:

    make it clear why you’re asking
    make sure the field works for all of your users
    help users to enter a valid email address

    You may also need to check that users have access to the email account they give you.

and here [1] is the github issue tracker for discussing email address patterns accepted by government services.

In respect of people without both first and last names, I resemble those remarks! I've dealt with broken computer systems since the 1990s that assume first+last (or even first+middle+last !), or set an arbitrary minimum length, and break when meeting me ("Tj") !

Worst cases for this are web services that set arbitrary rules for the name on a credit card (which can be almost anything by the rules and guidelines and should be free-form) - I had this only yesterday with onlyfans.com not accepting my name as it appears on the card because their rules impose first " " last format.

The double-abuse of the customer then comes when the first-line support, when told precisely what the problem is, and "please let your web-devs know", gets the response "Use a different card". Turned out that onlyfans.com (or their provider) don't even ensure the name matches when actually doing the authorisation since I put something random in for first-name and it was authorised.

I've discussed this in detail with my various bank's technical teams over the years and they've confirmed it usually isn't their side doing a DECLINE; it's the requesting service applying overly-strict arbitrary rules before deciding to make the authorisation request.

Again, GDS has recommendations (and consider this is for government services) for accepting names in free-form, not split into fields[2]. and says this:

    Use single or multiple fields depending on your user’s needs. Not everyone’s name fits the first-name, last-name format. Using multiple name fields mean there’s more risk that a person’s name will not fit the format you’ve chosen and that it is entered incorrectly.
In my case in the U.K. the passport office telephoned me once, for my first digital passport in the 1990s, asking rather apologetically if I'd mind them putting X's in the first name since their computer system couldn't cope with it being empty. Whereas the U.K. Driver and Vehicle Licencing Agency (DVLA) has no problem at all and shows my legal name correctly on my driving licence.

Two annoying exceptions (not strictly government created/operated) are the internal (local) NHS registration system and some local authority (local council) electoral role (voter registration) systems that do it badly - usually due to having bought in an external 'enterprise' application to handle it, or trying to interface many disparate systems.

Generally, over the last 25+ years, I've found government organisations are great at handling these corner cases but random private sector / out-sourced development is worst.

Getting traction to get things fixed is the hardest part - being treated as dumb (usually by first-line support and their 'managers') when I set out a clear case and rationale for the bug and how to fix it has to be amongst my least favourite voluntary community-spirited endeavours. The short-cut I apply there, now, is a an email CC-ed to the organisation head (chair, CEO) and senior legal person.

There is an up-side to it though - I rarely if ever suffer any kind of spam or phishing and anyone trying identity theft will have to have much more determination than me to overcome all the obstacles :P

[0] https://design-system.service.gov.uk/patterns/email-addresse...

[1] https://github.com/alphagov/govuk-design-system-backlog/issu...

[2] https://design-system.service.gov.uk/patterns/names/

[3] https://design-system.service.gov.uk/patterns/

iam-TJ··on WebKit on GitHub
For all the interesting ways to name an object, see [0]:

  man 7 gitrevisions
and for this particular naming "describeOutput"

[0] https://manpages.debian.org/bullseye/git-man/gitrevisions.7....

iam-TJ··on Things not available when someone blocks all cookies
I'd be tempted to nuance that:

  [ ] Cookies - stored locally and sent to web-sites automatically
  [ ] Local Storage - not automatically sent to web-sites
In all cases I veer towards sharing explicit details. If users choose to not understand it fully that is fine. I don't like 'dumbing-down' or simplifying taking away explicit details with no easy way to get it in the same place as the 'simple' exposition.
iam-TJ··on UK energy bills are soaring to record highs
But in this case "... Prices aren't determined by costs and never have been. Prices are only determined by supply and demand. ..." is patently incorrect!

OFGEM (Office of Gas and Electricity Markets) [0] imposes retail price caps based on what it considers 'fair' for the retailers, and this came about specifically because retailers were charging standard-variable-rate and pay-by-meter customers excessively as well as having far too many 'offers' that confused customers.

There's nothing to stop the government amending the legislation with a 1-clause Bill that gives OFGEM the power to impose a cap on the energy producers.

I agree about building wind farms. I'm on a farm where a neighbour wanted to install a single turbine for local generation but it was refused - due to NIMBYs in villages 2 miles away complained it would "spoil their view" despite the fact most of them are out at work all day and probably only see that view for 2 minutes a day, if that!

[0] https://www.ofgem.gov.uk/about-us/our-role-and-responsibilit...

iam-TJ··on UK energy bills are soaring to record highs
The price cap should be on the energy producers (wholesale) as well as the retailers.

This is just naked profiteering at the energy producer stage for those that aren't using natural gas as their sole energy source.

It isn't costing any more to produce electricity from nuclear, coal, hydro and renewable sources and yet these are being priced at the same rate as gas [0].

So, for example, British Gas (BG) and EDF are profiteering massively since they use no, or very little, natural gas.

All energy companies in the UK are required to publish their energy source mix. Here for example are the six largest producers[0]. There are many more smaller producers and associated retail suppliers that use them and many are focused on 'green' sources:

              Nuclear Coal  N.Gas  Renew Other Non-Gas Market Share[7]
    EDF[1]     62.1%  1.3%   7.5%  29.0%  0.1%   92.5%   18.52%
     BG[2]     35.0%  0.0%   0.0%  65.0%  0.0%  100.0%   23.70% (a)
    EON[3]      5.7%  3.5%  43.5%  43.7%  3.6%   66.5%   14.07%
    NPOWER[4]   6.9%  4.2%  52.6%  31.9%  4.4%   47.4%   24.07%
    SCOT PWR[5] 6.0%  4.0%  46.0%  40.0%  4.0%   54.0%   10.00%
    OVO/SSE[6]  0.0%  0.0%  49.6%  50.4%  0.0%   50.4%   18.50% (b)
So these six represent by far the majority. In fact adding up these market shares comes to 108.86%! That is because these companies supply both electricity and gas, sometimes separately, so one customer may get electricity from supplier A and natural gas from supplier B. That customer would be counted twice.

(a) British Gas is a trading name of Centrica which was formed when the original British Gas plc was split in a de-merger in 1997.

(b) OVO bought SSE in 2020.

[0] https://www.energycompanynumbers.co.uk/who-are-the-big-six-e...

[1] https://www.edfenergy.com/fuel-mix

[2] https://www.britishgasplus.co.uk/fuel-mix

[3] https://www.eonenergy.com/About-eon/Fuel-Mix

[4] https://npowerbusinesssolutions.com/company/fuel-mix

[5] https://www.scottishpower.co.uk/about-us/performance/fuel-mi...

[6] https://sse.co.uk/v3/assets/blt09078e271abddd45/blt04622618e...

[7] https://www.theenergyshop.com/energy-suppliers

iam-TJ··on Starlink is reducing your monthly service fee
I should have pointed out in the UK the cost includes 20% Value Added Tax (VAT) so the actual charge has reduced from £74.10 to £62.50 (US$87.44 to US$73.75 @ £1=US$1.18 on 2022-08-25).
iam-TJ··on Starlink is reducing your monthly service fee
Are all Starlink costs in dollars? Capital maybe, but operating costs?

In each legal domain (country ~ territory) Starlink operates in it has to install and operate one or more ground stations and back-haul into exchanges.

I realise there is a deal with Google for some of that - most likely it varies with the country, data-center locations, and exchange facilities.

But there are presumably ongoing costs to employ and support engineers to watch over the ground station physical assets and ensure back-up systems are always available?

iam-TJ··on Collapse of emergency healthcare in England may be costing 500 lives every week
It's exactly what I mean. There is absolutely no value in hanging on to the last possible moment due to ever increasing levels of interventions.

Living longer is not "a good thing" if that life is costing (not just in financial terms) society and the country so much more and the person can not sustain an independent quality of life.

In 1946-47, when the NHS, National Insurance (state pensions), and related programmes were created the average survival after retirement (60 for women, 65 for men) was 10 years or so (average mortality was 75 for men and little later for women).

So pension funding only needed to last on average 10 years and there was no comprehensive costly life-sustaining interventions to keep people alive that would otherwise have popped their clogs.

Now the average age of mortality in men is 85 and 89 for women, and these are rising. And as these are averages there are a lot of people lasting a lot longer - many spend years sitting in a chair effectively waiting for Death to show up.

So now the same pension funding has to provide for 20 or more years AND there are many costly and life-sustaining health interventions and "social care" that add cost and load on a dwindling number of tax payers.

I'm a farm-boy born n bred, as is my father, who is now 86. He's been amazingly fit his entire life but the last two years he's going rapidly downhill due to onset of mild dementia, but also due to not accepting doctors advice on treatments and medicines (this he's been doing for 40 years!) and subsequently hitting crisis where there have to be expensive emergency interventions.

As far as I am concerned he is abusing the NHS - like those who are obese or mistreating themselves in other ways - and if it were up to me I'd refuse to treat his emergencies if he is not prepared to look after himself by simply taking medicines that would prevent the emergencies.

Personally, I'll kill myself when I can no longer be useful.

Humans need to learn from how the rest of the planet's breathing life-forms treat life... and death, and lose the sentimentality. The planet already has twice as many humans on it as it can naturally sustain.

iam-TJ··on Collapse of emergency healthcare in England may be costing 500 lives every week
Increase in demand - much of which is attributed (by the NHS itself) for people having poor life-styles (meaning tending to obesity [0] and not maintaining physical and mental fitness), and the tendency for people to be kept alive longer existing with chronic conditions that a few decades ago would have naturally expired (dead!).

There's been an endemic problem for the last 30+ years where-by a large proportion of the population has a sense of entitlement to NHS care without at the same time bearing responsibility to keep themselves reasonably fit and healthy.

@ [0]: "Nearly two-thirds of adults in England are overweight or obese. In 2016/17, 617,000 admissions to NHS hospitals recorded obesity as a primary or secondary diagnosis"

[0] https://www.longtermplan.nhs.uk/online-version/chapter-2-mor...

iam-TJ··on Show HN: A web text-editor where you can write, compute and draw
What a uniquely quirky way to communicate! Glad to see via your sandbox update that you identified the cause.

Now all you need do is write "lambda-mta" to take over email!

Seriously - that 'free.fr' MTA spam block needs fixing if it triggers on proper 7-bit ASCII email that doesn't contain MIME parts (which are usually stuffed with HTML and/or images).

I use Mozilla Thunderbird in "Plain Text" mode. One benefit is there is no possibility to embed hidden malicious links in plain text. Another is small size (some embedded HTML emails are HUGE!).

← PreviousPage 5 of 11Next →